面试题:问以下代码输出的结果是多少?
public class IntegerTest { @Test public void test() { Integer a = 127; Integer b = 127; System.out.println(String.format("运行结果:%s", a == b)); a = 128; b = 128; System.out.println(String.format("运行结果:%s", a == b)); }}
如果不仔细看上面的代码,那么我想很多人都会很快的说出运行的结果。但如果仔细查看代码,却不知道上述代码中的要考察的相关知识时,我想也不一定能准确说出正确的运行结果。那么下面我们看一下上述代码的运行结果:
运行结果:true运行结果:false
你猜对了吗?为什么上面的代码显示的结果居然是不一样的呢?下面我们详细分析一下上述代码主要考察的知识点。
上述代码主要考察的是Java中Integer包装类对象的知识。但在这里有一个很隐性的知识点,也就IntegerCache对象。也就是因为这个对象的存在才导致上述代码中运行的结果不一致的。下面我们来了解一下Java中IntegerCache对象的知识。
IntegerCache
IntegerCache类实际上是Java中Integer中的缓存类,目的是节省内存消耗,提高程序性能。因为我们知道,在Java中每创建一个对象,都会将对象存储在堆内存中。而当堆内存中的对象存储非常多时,就有可能造成内存泄漏。而在我们日常的项目开发中我们使有用Integer类型的频率非常高。使用频率高创建对象也就越多,堆内存中的对象也就越多,所以也就会可能发生上述中的内存溢出等问题。所以Java为了解决上述问题。于是设计了IntegerCache类,看名字就知道IntegerCache是个缓存类,既然是缓存类,目的就是可以将相关的数据缓存下来,这里的数据指的就是Integer类的值。也就是上述代码中的等于右边的数值。那既然IntegerCache类可以缓存数字,为什么上述代码中的结果不一样呢?这个原因就是IntegerCache类有一个缓存范围。IntegerCache类缓存的数据范围为是-128到127之间。所以上述代码中前两行代码中输出结果为true(127在IntegerCache类缓存的数据范围内,于是将127缓存起来,当程序在使用这个127数字时,因为缓存中已经有了,于是直接使用缓存中的127,所以结果为true),而后二行代码输出的结果为false(超出IntegerCache类的缓存范围,于是不能缓存,所以创建了新的对象,既然是新的对象结果显然是false)。
为了验证我们上述我说的,我们看一下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) assert IntegerCache.high >= 127; } private IntegerCache() {} }
看源码中的注释我们知道,我们可以通过Jvm中的AutoBoxCacheMax参数来重新设置IntegerCache类的缓存范围。并且我们知道IntegerCache类使用了Integer cache[] 数据缓存数值。
这就是上述面试题中所要考察的相关知识,实际上除IntegerCache类之外,在Java中还提供了ByteCache、ShortCache、LongCache、CharacterCache等缓存对象,其中前三个缓存对象的缓存范围都是-128 到 127。而CharacterCache缓存对象则是0到127。这就是Java中IntegerCache类相关的知识,如有考虑不周,或者输写有误的地方,欢迎留言,谢谢。
原文链接: