综述
一般来说,“==”是用来比较两个对象在内存中的存放地址是否相同的。而equal方法是object类的方法,object类中的equal方法也使用“==”实现的,也就是说,如果直接继承object类的equal方法,则也是比较两个对象在内存中的地址是否相同。自定义类的时候,可以选择覆盖equal方法。
特殊情况
如果对象是基本类型的包装类或者字符串,那么情况就很有意思了。
首先我们应该明白,Java世界里面有字符串常量池。Byte,Character,Short,Integer,Long,Boolean存在相应的缓存(cache)。Float和Double没有缓存。
下面是jdk缓存的实现方式举例
public static Short valueOf(String s) throws NumberFormatException {
return valueOf(s, 10);
}
private static class ShortCache {
private ShortCache(){}
static final Short cache[] = new Short[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Short((short)(i - 128));
}
}
总结:Byte,Short,Integer,Long这些类产生的对象在-128~127之间都是有缓存的。
Character在0~127之间有缓存。
Boolean用静态常量TRUE,FALSE实现缓存。
valueOf()方法的实现方式
- 有缓存时
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
- 无缓存时
public static Double valueOf(double d) {
return new Double(d);
}
总结:valueOf()会返回缓存中的对象。
new关键字
Boolean b1 = new Boolean(false);
Boolean b2 = new Boolean(false);
System.out.println(b1 == b2); //false
new创建的对象不会从缓存中找,直接在Java的Heap(堆)中创建对象。所以得到的地址永远不会相等。
基本类型与包装类比较
Double d1 = 12.0;
Double d2 = 12.0;
double d3 = 12.0;
System.out.println(d1 == d2); //false
System.out.println(d1 == d3); //true,包装类型会转变成基本类型
System.out.println(d1.equals(d3)); //true
返回缓存中的地址
Integer i1 = 11; //i1就是指向缓存中的地址
Integer i2 = new Integer(11); //在heap(堆)中的某个位置
Integer i3 = Integer.valueOf(11); //i2就是指向缓存中的地址
System.out.println(i1 == i2); //false
System.out.println(i1 == i3); //true
System.out.println(i2 == i3); //false
没有缓存的情况
Integer i4 = 128;
Integer i5 = 128;
System.out.println(i4 == i5); //false, 128没有缓存
System.out.println(i4.equals(i5)); //true