一个很简单的小知识点
我们都知道,如果使用==
对比包装类型或对象,那么比较的都是两者之间的地址(指针或句柄),而非对象本身,那么且看下方的代码。
public class A {
public static void main(String[] args) {
// 类型1
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // true
// 类型2
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s3 == s4); // false
String s5 = "Hello";
String s6 = new String("Hello");
System.out.println(s5 == s6); // false
}
}
当前(JDK8)Java会把第一次出现的字符串放在元空间中,当再次出现相同的字符串时,新的字符串地址直接指向旧的字符串地址。因此类型1中的两个字符串的引用地址是一样的。
但是,被new出来的对象是被放入堆中的,堆可不管之前有没有一样的对象,因此"类型2"指向的地址是不一样的,因此"类型2"中的结果是false。
至于最下面,一个在元空间中,一个在堆中,那必然是不一样。
Integer又是怎么样的呢
public class B {
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1==i2); // true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3==i4); // false
Integer i5 = new Integer("1");
Integer i6 = new Integer("1");
System.out.println(i5 == i6); // false
}
}
上方的代码段中,第一段与第二段看起来除了数字"+1"了之外,毫无差异,为什么一个是true、而另一个却是false呢?
这是由于,Integer会缓存-128~127
之间的值,以减少内存的使用,所以当数字在-128~127
的范围内的时候,相同的数字也会引用相同的地址,因此代码段1的对比结果是true,但是当数字超出这个范围的时候,数字就不会被缓存,因此代码段2的对比结果是false。
至于代码段3,就不用说了吧,与String一致,new出来的对象放在堆中。
调整Integer的最大值
且看下面的代码:
两个为3000的Integer,运行出来的结果怎么会是true呢?这明显不符合第二章节的描述呀。
仔细看下执行命令,原来秘密在这里,除了基本的执行命令外,还加上了-XX:AutoBoxCacheMax=5000
,这个参数可以改变Integer缓存的最大值,我设置成了5000,那么3000<5000,当然也会被缓存啦,所以结果是true。