实际工作中在使用实体类的时候经常会覆盖三个来自 java.lang.Object 的方法: hashCode() , equals(Object) , 与toString()。
今天研究了一下,与大家分享一下。
首先看下 java.lang.Object 这个类中的这三个方法,我们都知道所有的class都默认继承这个类
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
从toString()方法的实现我们大概可以看出,这个方法实际上就是为了用一个字符串来表达一个物体而存在的,通过查看文档我们也可以看到对于这个方法的描述: Returns a string representation of the object.
通俗点的翻译就是用一个字符串来表达一个物体,当然了,在Java语言中一个物体我们就把它归为一个class了。
如果我们写一个类,并且没有覆盖toString()方法,那么我们直接调用它的toString()方法值时,返回的应该是"类名@哈希码"的格式,如下
那么问题来了,哈希码(HashCode)这个东西又是怎么来的呢?我们看到头String()方法中调用到了hashCode()方法
public native int hashCode();
这个方法没有方法体,因为调用的是用其他语言编写的代码。Java是高级语言,没办法直接对操作系统层级进行操作。这个地方理解的比较浅显,待深究。 我们再来看看hashCode()方法的文档,可以归纳出以下几点: 1.同一个Java应用执行过程中多次调用同一个类的hashCode()方法,应该保持返回值一致,多个应用执行不必保持一致 2.如果两个类通过equals方法比较相等,那么两个类hashCode()返回值也应该相等 3.通过equals方法比较不相等的两个类,不必要(not required)返回不同的hashCode,但是不同的Object有不同的hashCode有利于提高hash table的效率 可以看出来hashCode()这个方法和equals方法是有关联的,equals方法如下
public boolean equals(Object obj) {
return (this == obj);
}
它的文档中说明了如果equals方法被覆盖的,一般都需要覆盖hashCode方法(generally necessary),个人认为主要是为了保证两个方法的一致性。
equals与hashCode两个方法都是可以判断两个Object是否相等的,但是具体用法可能有差别。
举个例子,常用的 java.lang.String 类也覆盖了equals与hashCode两个方法
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;
}
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的value,用这两个方法比较的结果应该是一致的。
第一次写,思维比较混乱,想到什么写了什么,后续继续积累,相互学习