这种问题有点钻牛角尖,但相信想把JAVA学好学透的人都会喜欢。public class Test {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 200;
Integer i4 = 200;
if (i3 == i4) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
}
}结果:
i1==i2
i3!=i4这是为什么?
答案为白色,选中查看:
在用Integer比较的时候是会分两种情况的,当取值在-128~127之间时,是用原生数据类型,也就是int去作比较,除此之外都是用Integer,也就是比较它们的地址,所以才得出了以上的结果!
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 200;
Integer i4 = 200;
if (i3 == i4) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
}
}结果:
i1==i2
i3!=i4这是为什么?
答案为白色,选中查看:
在用Integer比较的时候是会分两种情况的,当取值在-128~127之间时,是用原生数据类型,也就是int去作比较,除此之外都是用Integer,也就是比较它们的地址,所以才得出了以上的结果!
public class 解包装包 {
public static void main(String []args) {
Integer a = 100;
Integer b = 100;
System.out.println(a==b);
}
}
打印结果为:true
但是如果换成 128 > var >= -128 之外的整数就打false了。
这是什么原因呢?
1。java在编译的时候 Integer a = 100; 被翻译成-> Integer a = Integer.valueOf(100);
2。比较的时候仍然是对象的比较
3。在jdk源码中
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
而
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache = new Integer(i - 128);
}
}
这边是java为了提高效率,初始化了-128--127之间的整数对象
所以在赋值在这个范围内都是同一个对象。
再加一句
Integer a = 100;
a++;
//这边a++是新创建了一个对象,不是以前的对象。
public static void main(String []args) {
Integer a = 100;
Integer b = a;
a++;
System.out.println(a==b);
}
打印就是false
对于127--128没有多大关系,但是在这范围之外就影响性能了吧,就像StringBuffer VS String一样了看了这么一篇文章JAVA为什么要这样做呢?真是学到了
Integer i1 = 100;
Integer i2 = 100;
if (i1.equals(i2)) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 200;
Integer i4 = 200;
System.out.println(i3);
System.out.println(i4);
if (i3.equals(i4)) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
我这个帖子的最后有说明
这个问题的确讨论很多次了。 这里再复习一次。
因为在JDK源码中Integer类有一个内部类IntegerCache,它默认创建了一个-128~127的Integer对象数组。
只要比较的是在这256个数内,就直接在对象池里查找并返回该对象。
这是Java处于性能的考虑,目的是节省内存。
至于范围之外的,不同的引用当然不相等了。
但不知道java为什么不像处理String那样,每创建出一个对象,就放到池里公用。也许sun经过统计发现字符串重用的可能性高,而整数重用的概率比较低吧。
因为SUN在设计这个INTEGER包装类的时候,考虑了效率问题,查看INTEGER类源代码就很明白了。
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Integer是一个包装类,属于引用类型比较的时候是用引用对象比较而不是内存值!所以用==是出发点错误了
而错误得到的结果不同是因为在Integer类中-128~128之间的数值都是已经初始化了的,以便给对象赋-128-128之间的值时,系统不要重新给这个对象开内存空间,目的在提高效率!
如果不在这个范围内,则创建一个新的Integer对象。
Integer i=Integer.valueOf(3);
而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.
简单测试.
Integer i=3;
Integer j=3;
我们测试i==j会发现它是true.
Integer i=129;
Integer j=129;
我们测试i==j会发现它是false.
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1.equals(i2)) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 150;
Integer i4 = 150;
if (i3.equals(i4)) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
}}
public class Test {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 128;
Integer i4 = 128;
if (i3 == i4) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
}
}输出是:
i1==i2
i3!=i4
第二种:public class Test {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("i1==i2");
} else {
System.out.println("i1!=i2");
} Integer i3 = 127;
Integer i4 = 127;
if (i3 == i4) {
System.out.println("i3==i4");
} else {
System.out.println("i3!=i4");
}
}
}
输出:
i1==i2
i3==i4
Integer有个内部类IntegerCache,它维护了一个Integer数组cache[] ,长度为256,还有一个静态块
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
很明显这个静态块已经默认认创建出了-128~127 的 Integer 数据
i1=100,i2=100是相等,而i3=200,i4=200不在自动装箱池,只能new,所以不等
int,char,short,byte,long,char是在5.0以后才有的
这个代码中的Integer i=100;是因为有自动封装的,只要是在-128~+127之间的就可以直接从int池中找,==比较的是地址是否相同,池中的100是只有一个的,所以地址是肯定相等的,所以两个是相等的
而200不在这个范围之内,它会指向堆里,所以是false
等同于
Integer i1 = Integer.valueOf(128); java.lang.Integer中关于valueOf的源码:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) {
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
就是说 如果int i,i的范围在i >= -128 && i <= 127范围之内 其地址空间没有变化,都指向同一地址。
如果超出这个范围,也就不在缓存的范围之内,其地址空间指向也会不同,立(Integer i3 = 200 会变成 Integer i3 = new Integer(200))。
在JDK5一下 这样的定义Integer i1 = 127会抱错。