==和equals()

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

  • 情况 1:类没有覆盖 equals()方法。则通过 equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
  • 情况 2:类覆盖了 equals()方法,则通过覆盖的方法进行对比。如Integer和String类中的equals()方法,是比较两个对象的值是否一样。

当只需要比较值是否相等时,用equals();除了值之外还需要比较地址相当时,用==。

一般而言,我们用==比较基础类型,用equals()比较包装类型。

 

用==比较包装类型的陷阱

Integer a = 100;
Integer b = 100;
Integer c = 300;
Integer d = 300;
System.out.println(a == b);
System.out.println(c == d);

 大家觉得以上代码会输出什么?都为true?不,结果是这样:

true
false

为什么c和d不想等呢?都是300啊。主观意识认为这两个是相等的。然而事实并非如此,为什么呢?

首先我们来看赋值,之前有讲这类赋值会自动装箱。调用的时Integer.vauleOf()方法,那我们来看源码:

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

 可以看到,这里有个IntegerCache类,会用输入的参数和它的最大最小值做对比,如果在范围内则返回缓存的值。再看看IntegerCache的源码。

/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;//最小值为-128
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;//初始最大值为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);//配置的值和127中取最大值
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);//如果配置的值大于Integer.Max_value-(low)-1,则最大值取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++);//从最小值开始存放:[-128,-127....high]

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

        private IntegerCache() {}
    }

相当于Integer有个内部类IntegerCache,把-128到127(最大值可设置),缓存了下来,每次取范围内都是返回同一个对象。

我们知道==比较的时对象的地址,a和b从缓存取到的地址是同一个,所以a == b为ture。而 300 不在缓存范围内,所以 c == d为false。

 

除了Integer类之外,其它包装类型也有对应的缓存范围,用的时候需要注意。

Boolean:ture false

Char:0~127

Byte: -128~127

Integer: -128~127(上限可设置,最大为Integer.MAX_VALUE - 129)

Long :-128~127

Short:-128~127

Double/Float:没有缓存

因为缓存的存在,所以在判断包装类型的时候尽量还是用equals()会好点,但是要注意空异常。

 

题外话:使用equals()时注意把非空对象放在首位,即  我不可能为空.equals(可能为空);

              或者使用objects中的equals()方法来对比两个对象,避免出现空异常。

posted @ 2020-03-12 20:58  迷思t无  阅读(165)  评论(0)    收藏  举报