Java详细分析讲解自动装箱自动拆箱与Integer缓存的使用(integer自动装箱原理)

网友投稿 420 2022-08-02


目录1. 前言2. 包装类3. 自动装箱与自动拆箱4. Interger缓存5. 回答题目

1. 前言

自动装箱和自动拆箱是什么?Integer缓存是什么?它们之间有什么关系?

先来看一道题目。

Integer a = new Integer(1);

Integer b = new Integer(1);

System.out.println(a==b);

Integer c = 1;

Integer d = 1;

System.out.println(c==d);

Integer e = 128;

Integer f = 128;

System.out.println(e==f);

先答,后看答案。

答案是false true false,你答对了吗?

既然一块出现了,就一起串一下知识点

2. 包装类

java中基本数据类型有八种,可以分为三类:

字符型:char布尔型:boolean数值型:byte short int long float double

包装类是将八种基本数据类型包装为了类,使它们可以使用Java的三大特性:封装、继承、多态。对应关系如下:

基本数据类型对应的包装类byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublebooleanBooleancharCharacter

数值型对应的六个包装类都继承于Number类。

3. 自动装箱与自动拆箱

八种基本数据类型对应八种包装类,那么它们是怎么进行数据转换的?

//基本数据类型转包装类

//1.有参构造

Integer a = new Integer(1);

//2.实际上,有参构造的参数也可以是字符串,不过要使用正确的数据,“123abc”不可能会转换为Integer类型

Integer b = new Integer("123");

//3.valueOf()

Integer c = Integer.valueOf(123);

//包装类转基本数据类型(xxxValue() float是floatValue() double是doubleValue())

int d = a.intValue();

以上的形式都是比较符合认知的,获取一个对象可以通过new或者调用某个方法,获取一个值就调用对象的某个属性。

Java 5.0之后可以不用这么麻烦了,增加了自动装箱和自动拆箱的新特性,实际上两个概念非常好理解。

int a = 10;

Integer b = a; //自动装箱

int c = b; //自动拆箱

乍一看,对象=数值的这种形式并不符合认知,但是借助于自动装箱和自动拆箱就可以实现。实际上,编译器还是借助于valueOf()和xxxValue()实现的。

我们来看一下valueOf()源码。

/**

* Returns an {@code Integer} instance representing the specified

* {@code int} value. If a new {@code Integer} instance is not

* required, this method should generally be used in preference tNifLPmPUwHo

* the constructor {@link #Integer(int)}, as this method is likely

* to NifLPmPUwHyield significantly better space and time performance by

* caching frequently requested values.

*

* This method will always cache values in the range -128 to 127,

* inclusive, and may cache other values outside of this range.

*

* @param i an {@code int} value.

* @return an {@code Integer} instNifLPmPUwHance representing {@code i}.

* @since 1.5

*/

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

valueOf()并不是简单地返回Integer对象,而是先进行了一次判断,输入的数据符合某个范围的话,将会返回一个特定的对象,从注释上来看,这个范围默认是[-128,127],并且可能是更大的范围;而超过这个范围就会返回new的对象。而使用到的IntegerCache数据就是Integer的缓存了。

4. Interger缓存

数值计算日常使用比较频繁,那如果不停的去new Integer对象的话,开销会非常大,所以,Java在执行程序时会自动生成一个静态数组作为缓存,Integer默认对应的缓存数组范围在[-128,127],只要数据在这个范围内,就可以从缓存中拿到相应的对象。

看一下IntegerCache源码。

/**

* Cache to support the object identity semantics of autoboxing for values between

* -128 and 127 (inclusive) as required by JLS.

*

* The cache is initialized on first usage. The size of the cache

* may be controlled by the {@code -XX:AutoBoxCacheMax=} option.

* During VM initialization, java.lang.Integer.IntegerCache.high property

* may be set and saved in the private system properties in the

* sun.misc.VM class.

*/

private static class IntegerCache {

static final int low = -128;

static final int high;

static final Integer cache[];

static {

// high value may be configured by property

int h = 127;

String integerCacheHighPropValue =

sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

if (integerCacheHighPropValue != null) {

try {

int i = parseInt(integerCacheHighPropValue);

i = Math.max(i, 127);

// Maximum array size is Integer.MAX_VALUE

h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

} catch( NumberFormatException nfe) {

// If the property cannot be parsed into an int, ignore it.

}

}

high = h;

cache = new Integer[(high - low) + 1];

int j = low;

for(int k = 0; k < cache.length; k++)

cache[k] = new Integer(j++);

// range [-128, 127] must be interned (JLS7 5.1.7)

asserthttp:// IntegerCache.high >= 127;

}

private IntegerCache() {}

}

可以看到,IntegerCache是Integer的静态内部类,valueOf()调用的IntegerCache.cache就是一个数组对象,数组的大小取决于范围内的最大值和最小值,默认是[-128,127],当然,(注释上说)也可以通过JVM修改这个范围(这我不了解)。然后数组内的元素都会被赋一个Integer对象,缓存也就形成了。

存在数组缓存,也就意味着,如果取值在[-128,127],使用valueOf()或者自动装箱创建的Integer对象都是在数组中取出,因此对象指向的内存地址是完全一样的。而如果用new或者是超出这个范围都要重新创建对象。

当然,不止Integer有缓存机制,Byte、Short、Long、Character都具有缓存机制。其中Byte,Short,Integer,Long的范围为 -128 到 127,Character的范围为 0 到 127。

5. 回答题目

Integer a = new Integer(1);

Integer b = new Integer(1);

System.out.println(a==b);

Integer c = 1;

Integer d = 1;

System.out.println(c==d);

Integer e = 128;

Integer f = 128;

System.out.println(e==f);

1.new创建的两个对象,即使值相同,指向的内存地址也是不同的,使用==进行比较返回结果为false

2.自动装箱和缓存机制,两个对象实际上是相同的,返回结果为true

3.超出缓存范围,执行时会new新对象,两个对象不同,返回结果为false


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:分布式医疗挂号系统Nacos微服务Feign远程调用数据字典
下一篇:java+mysql实现登录和注册功能
相关文章

 发表评论

暂时没有评论,来抢沙发吧~