一、Integer与Integer的比较
在使用Integer类型时,常常会不经意就使用==来做判断条件,但是下面的代码就出乎了我们的意料:
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println("a==b:\t"+(a==b));
System.out.println("c==d:\t"+(c==d));
我们预期的结果是不是 true true?
实际结果:
为什么会产生这样的问题?
是因为在java常量池中默认缓存了-128~127之间的整数,当Integer类型的对象值在此区间时,对象会直接去读取常量池的值,所以使用==比较时他们都指向同一个地址,但是一旦超出这个范围,Integer就会创建一个新的对象,这时两个Integer对象的地址就不同了,因此结果为false。
换种方式,我们使用Integer对象的equals方法再试一试:
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println("a==b:\t"+(a==b));
System.out.println("c==d:\t"+(c==d));
System.out.println("a.equals(b):\t"+a.equals(b));
System.out.println("c.equals(d):\t"+c.equals(d));
这次的结果应该很明显了,equals()比较的是两个对象中的值,输出结果:
结论1:我们在使用Integer对象进行值比较判断时,应该尽量使用其对象的equals()方法,以避免这种低级的bug。
以上情况在int类型中不会出现,int类型与Integer类型使用==比较时,Integer会自动拆箱为int类型,再进行比较,因此结果为true;Integer类型使用其对象的equals()方法与int类型进行比较时,int类型会自动装箱为Integer类型,再进行值比对,因此结果也是true。
二、Integer类型与其他基本类型之间的比较
有时候我们也经常将short、float、double、long、byte和char等类型进行比较,但是比较的结果真的会和我们预期的一样吗?下面我们就来试验一把。
代码:
Integer a = 127;
Integer b = 128;
short s1 = (short) 127;
short s2 = (short) 128;
Short s3 = (short) 127;
short s4 = (short) 128;
float f1 = 127.0F;
float f2 = 128.0F;
Float f3 = 127.0F;
Float f4 = 128.0F;
double d1 = 127D;
double d2 = 128D;
Double d3 = 127D;
Double d4 = 128D;
long l1 = 127L;
long l2 = 128L;
Long l3 = 127L;
Long l4 = 128L;
byte b1 = 127;
Byte b2 = 127;
char ch1 = 127;
char ch2 = 128;
Character ch3 = new Character(ch1);
Character ch4 = new Character(ch2);
System.out.println("--------------short--------------");
System.out.println(a==s1);
System.out.println(b==s2);
System.out.println(a.equals(s1));
System.out.println(b.equals(s2));
System.out.println("---------------Short-------------");
// System.out.println(a==s3);// 编译异常
// System.out.println(b==s4);// 编译异常
System.out.println();
System.out.println();
System.out.println(a.equals(s3));
System.out.println(b.equals(s4));
System.out.println("--------------float--------------");
System.out.println(a==f1);
System.out.println(b==f2);
System.out.println(a.equals(f1));
System.out.println(b.equals(f2));
System.out.println("---------------Float-------------");
// System.out.println(a==f3);// 编译异常
// System.out.println(b==f4);// 编译异常
System.out.println();
System.out.println();
System.out.println(a.equals(f3));
System.out.println(b.equals(f4));
System.out.println("--------------double--------------");
System.out.println(a==d1);
System.out.println(b==d2);
System.out.println(a.equals(d1));
System.out.println(b.equals(d2));
System.out.println("---------------Double-------------");
// System.out.println(a==d3);// 编译异常
// System.out.println(b==d3);// 编译异常
System.out.println();
System.out.println();
System.out.println(a.equals(d3));
System.out.println(b.equals(d4));
System.out.println("---------------long-------------");
System.out.println(a==l1);
System.out.println(b==l2);
System.out.println(a.equals(l1));
System.out.println(b.equals(l2));
System.out.println("---------------Long-------------");
// System.out.println(a==l3);// 编译异常
// System.out.println(b==l4);// 编译异常
System.out.println();
System.out.println();
System.out.println(a.equals(l3));
System.out.println(b.equals(l4));
System.out.println("---------------byte-------------");
System.out.println(a==b1);
System.out.println(a.equals(b1));
System.out.println("---------------Byte-------------");
// System.out.println(a==b2);// 编译异常
System.out.println();
System.out.println(a.equals(b2));
System.out.println("---------------char-------------");
System.out.println(a==ch1);
System.out.println(b==ch2);
System.out.println(a.equals(ch1));
System.out.println(b.equals(ch2));
System.out.println("---------------Char-------------");
// System.out.println(a==ch3);// 编译异常
// System.out.println(b==ch4);// 编译异常
System.out.println();
System.out.println();
System.out.println(a.equals(ch3));
System.out.println(b.equals(ch4));
再看下运行的结果:
结论2:Integer在和其他基本类型进行比较时,若Integer类型使用==和其他基本类型的拆箱模式比较其结果都为true,Integer类型对象使用equals()方法和其他基本类型拆箱模式进行比较其结果都为false;若Integer类型使用==和其他基本类型的包装类型进行比较时都会报编译异常,无法进行比较,Integer类型对象使用equals()方法和其他基本类型的包装类进行比较其结果都为false。
另外我注意到一个问题,在idea编译器中,我的a.equals(c)的这类方法它都警告我,其结果会一直是true,看截图:
但是我们从运行结果来看,idea的判断完全是错误的,因此我们有时候也不能完全信任编译器。