Integer
本身是int
的包装对象,是Number
的子类。
问题
Java中的经典引用判断问题,除了String
还有Integer
。本来以为只会在面试题里遇到,结果真的在项目中遇到了。以下是代码表现:
1 | Integer a = 28; |
通过不同的手段对Integer
进行赋值,然后判断相同值的引用是否相同。
答案
首先对于看过源码的开发者应该知道答案:
1 | false |
解释
因为在Integer
中有一个缓存类IntegerCache
,用来减少Integer
对象的创建。不过毕竟默认的缓存也不能占用太多,否则就适得其反,所以Java中就给定了缓存区间 -128~127
。
所以在a
、b
、c
和d
四个变量中,除了b
是new
出来的,其他的都是从缓存值获取的,通过==判定其引用是同一个,所以相等。在a2
、b2
、c2
和d2
中,由于其大小超出了默认缓存值,所以大家都是各自的新引用,也就各不相同了。
延伸
官方注释
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 -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.
也就是说,我们可以通过-XX:AutoBoxCacheMax=<size>
来设定缓存最大值,但是缓存的最小值已经被final掉了,固定是 __-128__,这个改变不了。
拓展问题
基于问题中的变量,我们进行以下方式的操作,结果又如何呢:
1 | a += 99; |
答案是都相同,因为这时,所有的变量值都处于Integer
缓存值区间,引用的都是缓存值。也就是说如果这四个变量加的是100,那么它们的值达到了128
,就会由新的Integer
对象来接管,使得这四个变量各不相等。