今天在一个技术群在火热讨论Java基础问题,看了下Integer 和 int的之间的瓜葛,懵逼了。忘记的一干二净,于是重新研究了一下,做个记录。
Integer直接赋值时会自动装箱,装箱的会判断当值在Integer常量池(-128~127)范围内,将会直接从常量缓存池SMALL_VALUES中取,生成的Integer对象是同一个地址值。当不在这个范围内时会直接new一个Integer来创建对象。
我们可以看一下Integer源代码
//Integer中的装箱的代码
public static Integer valueOf(int i) {
return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}
private static final Integer[] SMALL_VALUES = new Integer[256];
static {
for (int i = -128; i < 128; i++) {
SMALL_VALUES[i + 128] = new Integer(i);
}
}
可以在上面看出来,Integer在静态代码块中初始化了赋值-128到127的Integer对象放在SMALL_VALUES中缓存着。装箱代码中判断当前值是否在常量池范围内,不在就重新new了一个integer
先看看第一种情况
public static void main(String[] args) {
Integer a1 = new Integer(100);
Integer b1 = 100;
System.out.println("a1== b1:" + (a1 == b1));
Integer a2 = new Integer(150);
Integer b2 = 150;
System.out.println("a2== b2:" + (a2 == b2));
}
输出为:a1== b1:false | a2== b2:false
a1是直接new出来的一个对象,value是100;
b1 是直接赋值的,上面有说过会自动装箱,这里的值在常量池范围内,直接取的是SMALL_VALUES中相对应的对象
a1、b1都是对象,所以比较的是地址,一个是自己new出来的,一个是SMALL_VALUES中取出来的,一般情况下两个地址是不可能相同的,所以false
a2是直接new出来的一个对象,value是150;
b2由于超出常量池范围,会直接new一个对象,两个地址是不相同的,所以false
第二种情况
public static void main(String[] args) {
Integer a1 = 100;
Integer b1 = 100;
System.out.println("a1==b1:"+(a1 == b1));
Integer a2 = 150;
Integer b2 = 150;
System.out.println("a2==b2:"+(a2 == b2));
}
输出为:a1==b1:true| a2==b2:false
a1.b1是自动装箱产生的对象,其值都是100,在常量池范围内,所以都是去SMALL_VALUES中取,那自然就是一个对象了,所以true
a2.b2也是自动装箱产生的对象,但是值超出了常量池范围,显然这两个对象都是new出来,在堆中的地址值是不同的,所以false
第三种情况
public static void main(String[] args) {
Integer a = new Integer(3);
int b = 3;
System.out.println("a==b:" + (a == b));
}
输出为:a==b:true
a直接new出来的一个对象,value是3;
b 是int基本类型,直接存的数值,为3;
a与b比较时,a会自动拆箱调用intValue()方法拿到value,然后与b进行比较,value是int基本类型.所以为true