为什么项目中Integer做比较尽量不要用==

500 阅读2分钟

要知道上面的答案必须先了解下==和equals的区别还是Integer的基本方法

1.==和equals区别

  1. 基本类型: byte,short,int,long,float,double,char,boolean(该8种类型是存在栈中的)
  2. 引用类型: 除以上8种剩下的就是引用类型(该类型真正的值存在堆中,栈中存了该值的的引用值)
  3. ==:是比较的栈中的值,也就意味着对于基本类型比较的是真正的值,对于引用类型比较的是存在栈中的引用值
  4. equals:分为两种情况,一种是未重写equals(其本质也是==),一种是重写了equals(例如Integer,String等)这种比较的就是真正的值而不是引用值

2.Integer详解

先看下面的代码以及运行结果:

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

通过以上的实现我们发现i3和i4用==去比较居然时false,那么为什么会出现这种情况呢,我们继续深究!

由于在i3 == i4 比较时jdk会做自动装箱操作,即调用了如下方法:


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


IntegerCache:
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

解释:
我们通过代码可以发现jvm本身就缓存了[-128,127]内的数字,所以当我们使用不在这个区间里的数字会导致
走这个代码return new Integer(i); 这个时候我们用==比较的时候就比较的引用的值,所以最终导致false的出现

问题:
那么==不能用来比较那我们看看equals是如何处理的,如下:

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

解释:
重写equals方法,这个时候就变成了
Integer(128) == int(128),这个时候jdk会自动拆箱,最终用==比较的是基本类型int也就是值而不是引用值

通过以上代码我们应该也懂得了为什么Integer尽量不要用==,希望大家在代码里除了基本类型外其余的都用equals去做比较。