目录
问题来源自讲课时的Integer练习中
当时第一反应是false true true
因为第一段的输出为flase毋庸置疑了,因为已经new了两个新的堆空间,当然指向不同的空间了
但是第二段第三段就没有头绪了,自动装箱了难道不是执行同一个空间吗 。
实际上要看自动装箱时的隐式调用Integer.valueOf的源代码
输出为false true true
第一段是对的,但第二端隐式调用了Integer的valueOf方法,使用debug可以追入
进入该方法后,可以看到有if语句分别判断执行两个return,先看if里面的
if (i >= IntegerCache.low && i <= IntegerCache.high)
这一句话里面的IntegerCache.low和.high是谁呢?接着追入可以发现
这个low和high在本类开头已经声明了,而且是静态的,在类加载的时候就已经赋值完毕了,low=-128。
这段源码重要的是看if语句有没有执行,而在这个if语句块内,执行的是判断有没有在虚拟机初始化时设置初始值,如果没有设置初始值,将默认为空,因为getSavedProperty方法返回java.lang.String为空
- String integerCacheHighPropValue =
- sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
调用虚拟机的获取设置,编译时不输入就为空
public static java.lang.String getSavedProperty(java.lang.String s) { /* compiled code */ }
为空不执行if语句high被赋予默认值127,所以min = -128,high = 127
到目前为止,我们解决了if判断是从-128 && 127的值(127可以通过jvm设置)
接下来探讨return后面的一串是什么东西
首先是cache,我们可以发现格式是一个数组,使用查找可以找到在本来开头定义了一个对象数组
注意,这里的对象是static的,所以在类加载的时候编创建好了,我们再找找该静态对象在哪里被赋值或者创建
查找可以发现,cache数组对象在类被调用时创建了个大小为127+128+1大小的数组,通过for循环赋值从j++也就是-128 ++直到255,这时的k循环从0~255,数值大小循环为-128到127。
随后if语句块内的就很好理解了,cache已经是静态对象而且被创建好了,直接返回对应的数值的数组对象下标回去即可,这一个机制也叫JDK的内部缓冲
这个就没什么好解释的了,在-128到127范围之外的我简单粗暴的new一个int i 的值的对象返回给你就行了
更多关于该JDK内部缓冲的分析请参考
OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)_51CTO博客_openjdk使用
因为题目的第二段我们赋的值是int常量,使用自动装箱隐式调用valueOf方法,在该方法内if判断为真,返回静态对象cache[129] = Interger(1)回去,所以此时的m指向Interger(1)对象,然后第二句同理,n也指向Interger(1)对象,所以sout(m == n)打印为true
然后第三段,前面的都同理,但x和y都不在-128~127内在if判断时为假,直接new一个新空间,所以x和y当然执行两个不同的新空间,所以==为false
所以正确答案为 false true flase,完毕
- /**
- * @author 银海
- * @version 1.0
- */
- public class WrapperExercise02 {
- public static void main(String[] args) {
- Integer i = new Integer(2);
- Integer j = new Integer(1);
- System.out.println(i == j); //False
- //所以,这里主要是看范围 -128 ~ 127 就是直接返回
- /*
- 老韩解读
- //1. 如果i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
- //2. 如果不在 -128~127,就直接 new Integer(i)
- public static Integer valueOf(int i) {
- if (i >= IntegerCache.low && i <= IntegerCache.high)
- return IntegerCache.cache[i + (-IntegerCache.low)];
- return new Integer(i);
- }
- */
- Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码
- Integer n = 1;//底层 Integer.valueOf(1);
- System.out.println(m == n); //T
- //所以,这里主要是看范围 -128 ~ 127 就是直接返回
- //,否则,就new Integer(xx);
- Integer x = 128;//底层Integer.valueOf(1);
- Integer y = 128;//底层Integer.valueOf(1);
- System.out.println(x == y);//False
-
- }
- }
- /**
- * 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++);
-
- /**
- * 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) {
- if (i >= IntegerCache.low && i <= IntegerCache.high)
- return IntegerCache.cache[i + (-IntegerCache.low)];
- return new Integer(i);
- }
- /**
- * The value of the {@code Integer}.
- *
- * @serial
- */
- private final int value;
-
- /**
- * Constructs a newly allocated {@code Integer} object that
- * represents the specified {@code int} value.
- *
- * @param value the value to be represented by the
- * {@code Integer} object.
- */
- public Integer(int value) {
- this.value = value;
- }
- }