==和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()方法来对比两个对象,避免出现空异常。

浙公网安备 33010602011771号