版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010323023/article/details/52920605
不得不说,这是一个很有趣的知识点。如果运行下面的代码:
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
你会得到一个非常有趣的结果:
结果出乎意料吧,我们知道,Java在比较两个对象的时候是比较他们的引用,就是说如果两个对象的引用相同,那他们的==结果才是true,按照这个思路想,上面的代码都应该是false才对。
这就是它有趣的地方了。如果你看去看 Integer.Java 类,你会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象。
当我们创建Integer对象的时候
Integer a = 100;
其实内部的操作是下面这样的:
Integer a = Integer.valueOf(100);
然后再看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 to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield 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} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
看看注释大致就明白了。如果值在-128到127之间,就从缓存里面取值,这样两次得到的是同一个实例,因此上面的100 == 100.
现在你可能会问,为什么这里需要缓存?
合乎逻辑的理由是,在此范围内的“小”整数使用率比大整数要高,因此,使用相同的底层对象是有价值的,可以减少潜在的内存占用。
下面,我们通过反射去修改这个内部缓存类中的数组,会得到题目中说的3 + 3 = 12。
public static void main(String[] args) throws NoSuchFieldException,IllegalAccessException {
Class cache = Integer.class.getDeclaredClasses()[0]; //得到IntegerCache类
Field myCache = cache.getDeclaredField("cache"); // 得到cache数组对象
myCache.setAccessible(true); //将数组对象的可访问性设置为false
Integer[] newCache = (Integer[]) myCache.get(cache); //返回IntegerCache对象上"myCache"表示的字段的值([-128~127])
newCache[134] = newCache[140]; //6 = 12
Integer s = 6;
System.out.println(s);
Integer a = 3;
Integer b = a + a;
System.out.println(b);
int c = 3;
int d = c + c;
System.out.printf("%d + %d = %d", c, c, d);
}
下面就是我们要的结果:
相信注释已经写的很明确了,快去自己的环境上试试吧!