Java 两个Integer对象的==判断时由于自动装箱而出现的奇怪问题

Integer是int的包装类,既然是类,Integer类型的变量进行==比较的时候就是判断两个对象引用的地址是否相同了。
因此下列代码的返回值为false

public static void main(String[] args) {
    
    
        Integer i1 = new Integer(1);
        Integer i2 = new Integer(1);
        System.out.println(i1 == i2);//false
    }

这个比较好理解,因为每次new操作,都会在堆空间中申请一个新的对象。他们的地址肯定不同。
但是下列代码的结果呢?

public static void main(String[] args) {
    
    
        Integer i1 = 1;
        Integer i2 = 1;
        System.out.println(i1 == i2);//true
    }

这段代码的结果竟然是True。
1是int类型,他会自动装箱成Integer,也就相当于

public static void main(String[] args) {
    
    
        Integer i1 = Integer.valueOf(1);
        Integer i2 = Integer.valueOf(1);
        System.out.println(i1 == i2);//true
    }

但是这样貌似也不能解释为什么i1和i2引用的地址会相同。
别着急接着往下看

public static void main(String[] args) {
    
    
        //Integer i1 = Integer.valueOf(128);
        //Integer i2 = Integer.valueOf(128);
        Integer i1 = 128;
        Integer i2 = 128;
        System.out.println(i1 == i2);//false
    }

什么!?这段代码的返回值竟然是False
那么这是什么原因造成的呢。
首先我们知道,int在赋值给Integer的时候会自动装箱成Integer
即下列两行代码是等价的

 		Integer i1 = Integer.valueOf(128);
        Integer i1 = 128;

然后我们打开Integer.valueOf()的源码

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

其中的IntegerCache.low又是什么呢?
在这里插入图片描述

到这里谜题就揭晓了,原来Integer早就把-128到127的数字帮我们缓存好了,如果我们调用Integer.valueOf()方法的话,会判断传入的参数是否在这个范围内,如果在的话,就返回缓存好的Integer对象。
其他的包装类也有相似的缓存机制。
因此我们在判断包装类是否相等时,最好用equals()方法而不要用== (当然Boolean类型无所谓啦,因为他只有两种可能,这两种早就被缓存好了)

猜你喜欢

转载自blog.csdn.net/qq_30033509/article/details/115052402