Java Integer比较

下面通过几个代码案例来详解说明Integer类比较的问题和需要注意的地方

比较一

public static void main(String[] args) {

        Integer a = 10;
        Integer b = 10;
        System.out.println("a == b  " + (a == b));
        System.out.println("a.equals(b)  " + (a.equals(b)));
        System.out.println("a.intValue() == b.intValue()  " + (a.intValue() == b.intValue()));
        System.out.println("a.compareTo(b)  " + (a.compareTo(b)));
        System.out.println("---------");

        a = new Integer(10);
        b = new Integer(10);
        System.out.println("a == b  " + (a == b));
        System.out.println("a.equals(b)  " + (a.equals(b)));
        System.out.println("a.intValue() == b.intValue()  " + (a.intValue() == b.intValue()));
        System.out.println("a.compareTo(b)  " + (a.compareTo(b)));
        System.out.println("---------");

        a = 189;
        b = 189;
        System.out.println("a == b  " + (a == b));
        System.out.println("a.equals(b)  " + (a.equals(b)));
        System.out.println("a.intValue() == b.intValue()  " + (a.intValue() == b.intValue()));
        System.out.println("a.compareTo(b)  " + (a.compareTo(b)));
        System.out.println("---------");

        int m = 189;
        int n = 189;
        System.out.println(m == n);
    }

运行结果

a == b  true
a.equals(b)  true
a.intValue() == b.intValue()  true
a.compareTo(b)  0
---------
a == b  false
a.equals(b)  true
a.intValue() == b.intValue()  true
a.compareTo(b)  0
---------
a == b  false
a.equals(b)  true
a.intValue() == b.intValue()  true
a.compareTo(b)  0
---------
true

在Java中==是比较的两个对象所指向的内存地址是否相等,而equals方法比较的是值。如果按照这个理论,上面的结果中可以看出Integer a = 10;Integer b = 10;这两个对象内存地址是同一个,也就是a和b两个引用指向同一个对象。而Integer a = 189;Integer b = 189;中,a和b两个引用指向了两个不同的对象。


通过Integer源码可知: 
- Integer是不可变对象,因为里面的value是final的private final int value; 
- 128到127之间的数据放到了IntegerCache中,IntegerCache是static的,因此将会放到常量池中作为缓存使用

因此可知,Integer a = 10;Integer b = 10;这两个对象其实是从IntegerCache缓存中取的,是同一个对象,地址肯定是相同的。而Integer a = 189;Integer b = 189;是创建的两个新的对象,因此地址肯定不同的。

比较二

public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        System.out.println(c == d);
        System.out.println(e == f);
        System.out.println(c == (a + b));
        System.out.println(c.equals(a + b));
        System.out.println(g == (a + b));
}

//output:
true
false
true
true
true

怎么也想不明白为什么c == d为true,而e == f却为false。然后测试了几个不同的数值,到127时还是true而当值为128时结果就为false了。而128刚好是2^7,因此应该是有个范围的。

然后Google了一下,看到大家的解答才恍然大悟,原来在java中,在我们用Integer a = 数字;来赋值的时候Integer这个类是调用的public static Integer valueOf(int i)这个方法。

而valueOf()函数的源码为:

public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); } 

这样可以发现对传入参数i做了一个判断。在-128<=i<=127的时候是直接用的int原始数据类型,而超出了这个范围则是new了一个对象。我们知道"=="符号在比较对象的时候是比较的内存地址,而对于原始数据类型是直接比对的数据值。所以出现了上面比较e,f返回false的结果。