equals和==我该用哪一个

249 阅读2分钟

前言:今天工作的时候,看到sonar扫描出来的bug,Long类型的比较时,老哥使用了==,sonar给出的建议是使用equals。简单记录一下equals和==什么时候用。

1.euqals和==的区别

1.==

对于基本类型而言,比较的是值相等。例如:byte,short,int,long,float,double,char,boolean等等

对于对象而言,比较的是地址相等。例如:基本类型的包装类,自定义的对象等等

2.equals

object中的equals()方法

public boolean equals(Object obj) {
    return (this == obj); 
}

原本的equals()方法也是使用==进行比较

之所以String这种能够实现值的比较,是因为equals()方法被重写了。所以具体equals()方法比较什么内容就要看具体的对象中怎么重写的这个方法。

//String中的equals()
public boolean equals(Object anObject) {
        //比较的是同一个对象,返回true
        if (this == anObject) {
            return true;
        }
        //将字符串转成字符数组挨个比较
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

2.Long类型为什么用equals比较?

对于Byte,Short,Integer,Long这些包装类比较值相等的时候,可以用==或equals()

== 使用有一定的范围,在-128~127内可以使用==。这个范围的对象会被缓存下来,生成这个范围的对象时会从缓存里拿。所以同一个数值生成的会是同一个对象。

//Long类型缓存的对象
private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}


//生成Long对象时判断是否在这个范围内,在的话就从缓存中拿
public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { 
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}

使用equals()比较,方法已经被重写,比较的是值

//Long中的equals()方法
public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

Integer 中缓存的范围 可以根据我们带的参数进行设置,默认为 [-128,127]

//缓存范围的最小值为-128,最大值在[127,Integer.MAX_VALUE - (-low) -1]之间(low = -128)
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() {}
}


生成对象也是根据缓存的范围返回
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

3.为什么equals()要与hashCode()同时重写

目的:提高效率

自定义的对象进行比较,调用自己重写的equals()方法比较即可。

在一些数据结构中例如Map,Set中会先调用hashCode(),不出现哈希碰撞意味着没有重复值会直接插入值。如果出现哈希碰撞,则调用equals()进行比较。提高了插入效率,不用把所有对象都进行equals比较。(Map,set底层数据结构是数组加链表,会调用hashCode()对数组长度取余决定放在哪个数组位置,在数组同一个位置的不同对象会用链表窜起来)

原则:equals()相等则hashCode()一定相等。hashCode()相等则equals()不一定相等