1. 遇到问题
昨天刷题的时候遇到一个很有趣的整数比较的问题, 整理如下:
(1)
int i = 127;
int j = 127;
System.out.println(i == j);
int i = 128;
int j = 128;
System.out.println(i == j);
这两个输出应该都是true,没有问题。
(2)
Integer i = 127;
Integer j = 127;
System.out.println(i == j);
Integer i = 128;
Integer j = 128;
System.out.println(i == j);
第一个输出的是true, 第二个输出的是false, 这里就比较有意思了,哈哈~
(3)
Integer i = new Integer(127);
Integer j = new Integer(127);
System.out.println(i == j);
Integer i = new Integer(128);
Integer j = new Integer(128);
System.out.println(i == j);
这两个输出的都是false, emmmmmmmmmm, 是不是有点懵圈。。。。。
2. 解决问题
首先,应该知道java中的自动装箱和自动拆箱机制。简而言之,就是在Java中,jvm会自动实现基本数据类型和与之相对应的类的之间的自动转换。例如int和Integer之间能够自由的转换。
其次,应该明白对象之间用“==”比较,比较的是内存中的对象是否一样(可以理解为地址是否一样)。
然后,对于第一种情况,两个int之间的比较,比较的是数值,符合我们的常规认识。 对于第二种情况,127之间的比较返回true, 128之间的比较返回false,是因为jvm中包含一个整数池(pool of Integer values ) ,这个Integer Pool只包含-128 - 127。所以当创建一个-128到127之间的Integer时,会自动引用池中的对象,故127之间的比较返回true,而创建小于-128或大于127的Integer时,则会另外单独创建,所有两个128是不同的对象,他们之间的比较自然返回false。对于第三种情况,采用 new关键字创建整数对象时,会在内存中创建不同的对象,所以这种情况下,不管value大小,他们之间的比较必然返回false。
3.总结
(1)整数之间直接用“==”比较大小,可能会出现autoboxing-same-value-to-different-objects问题;
(2)int之间用”==”比较,比较的是二者值是否相同;
(3)jvm中有一个Integer Pool,包含-128 - 127之间的整数对象。当采用直接赋值的方法创建Integer时,能用池中对象直接表示的,会继续引用池中的对象,超出范围的才会创建新的对象(这也是jvm节省内存空间的一种策略);
(4)采用new关键字创建Integer对象时,会创建新的对象,而不是引用整数池中的对象。
4. Objects.equals()方法
尝试了一下,不用“==”进行上述的比较,而用Objects.equals()方法进行上述的比较。
int i1 = 127;
int j1 = 127;
System.out.println(Objects.equals(i1, j1));
int i2 = 128;
int j2 = 128;
System.out.println(Objects.equals(i2, j2));
Integer i3 = 127;
Integer j3 = 127;
System.out.println(Objects.equals(i3, j3));
Integer i4 = 128;
Integer j4 = 128;
System.out.println(Objects.equals(i4, j4));
Integer i5 = new Integer(127);
Integer j5 = new Integer(127);
System.out.println(Objects.equals(i5, j5));
Integer i6 = new Integer(128);
Integer j6 = new Integer(128);
System.out.println(Objects.equals(i6, j6));
上述结果输出的都是true, 如何理解呢?emmmmmmmmm……….
先看Objects.equals方法的说明:
Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
所以这个方法会调用第一个参数的equals方法,上述例子中也就是调用Integer的equals方法。而Integer的equals方法比较的是两个整数的int value值是否相同,故返回true。