错题二:Integer的直接赋值问题
考察的知识点:Integer直接赋值实际上是调用了Integer类的静态方法valueOf(int i)。
原始题目:
答案是D。
我当时的选择是A,先说一下我当时错误的思路:首先我并不知道Integer的直接赋值时调用valueOf方法,所以我认为第一个和第三个的结果应该是相同的,要不都为true,要不都为false;第二点我是知道第二个String的比较一定是false的,所以我只好选了A。
现在对这道题目进行详细的分析:
1.Integer的直接赋值实际上是调用了Integer类的valueOf静态方法,源码如下:
我们可以看到它首先是去与一个范围进行比较,如果在这个范围中,则返回IntegerCache中cache数组对应位置的值,否则调用Interger的构造方法new一个新的对象。
IntegerCache类的部分源码如下:
首先我们看到了IntegerCache是一个静态内部类,从中我们可以得知low和high的范围,即[-128, 127],其中还有一段静态代码块将这个范围内的数依次构建Integer对象存到了cache中去,所以cache是存储着-128到127的Integer对象的。现在我们回头看valueOf方法,我们可以知道如果数值在-128到127之间,声明的Integer变量会直接指向已经构建好的Integer对象,否则会构建新的Integer对象。
明白了原理,我们回归到题目上面,当Integer赋值为128时,不在[-128,127]的范围内,生成新的Integer对象,所以i1和i2指向的是两个不同的对象,结果为false;赋值100时,在[-128,127]的范围内,所以,i5和i6指向的是同一个Integer对象,结果为true。
现在我们来看String这个比较。首先String i3 = "100"是在常量池中生成了一个字符串"100",而String i4 = "1" + new String("00")是先在常量池中生成了"1",然后在常量池中生成了"00",然后在堆中生成了一个对象指向了常量池中的"00",而字符串常量和变量进行拼接实际上是StringBulider的append方法实现的,最终还是生成一个新的String对象,这个对象指向了常量池中的"100",i4这个引用指向了新的对象,所以i3跟i4的地址肯定不可能相同,故为false。