==
根据我的理解,==比较变量的值是否相等,即变量对应的栈中存放的存放的数值是不是相等的。因为基本类型的数据直接存放在栈中,所以只要值相等,==就返回true。而对于对象来说,栈中存放的是Java对中对象的地址(直接指针访问)或者句柄池中句柄的地址(句柄访问)。所以==比较的是,两边是否为同一个对象(对象的地址是否相同)。
equals()
equals方法是Object类的公开方法,具体作用根据类的不同而有所变化。
// Object类
public boolean equals(Object obj) {
return (this == obj);
}
从源码可以看出,Object类中的equals方法其实就是==。注释上还写明:equals方法表示,一个对象“等于”另一个对象,这个方法对于非null对象具有等价性。
等价性(限于非null对象):
- 自反性:x.equals(x)返回true。
- 对称性:x.equals(y)与y.equals(x)的返回结果应该相同
- 可传递性:x.equals(y)返回ture,y.equals(z)返回true,那么x.equals(z)也应该返回true。
- 一致性:只要equals方法中要比较的信息没有修改,那么即使多次调用x.equals(y),返回的结果应该都是相同的。
重写equals方法时,一般也要重写hashcode方法,保证等价的对象要有相同的哈希码。
// String类
public boolean equals(Object anObject) {
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;
}
在String类中,equals方法被重写了。根据源码,先使用==判断比较的两个对象是否为同一个对象。如果不是的话,再使用instanceof判断要比较的对象是否为String类型。接着比对两个字符串的长度,再比较其字符序列是否相同。
// AbstractMap类
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key)==null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
在Abstract类中重写的equals方法,同样也是先判断比较的对象是否为同一个,然后用instanceof判断类型,用size方法判断大小。接着遍历被比较的Map实例,如果value为null,那么比较m是否有这个key,并且该key对应的value值也为null。如果value不为null,那么比较两个value存放的对象是否等价。
hashCode()
// Object类
public native int hashCode();
hashCode返回对象的哈希码值,它的一般规约有:
- 多次调用同一对象时,返回的哈希码值应该相同。
- 如果两个对象等价(调用equals方法返回true),那么它们的哈希码值一定也相同。
- 不等价的对象的哈希码值不一定不同。尽量使其不相同。
等价的对象的哈希码值一定相等,相同哈希码值的对象不一定等价。
// String类
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
String类的哈希码的计算方式是:s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1]。其中s[i]是字符串的第i个字符,n是字符串的长度,^表示取幂。 (空字符串的散列值为零。)
网友评论