Theo dõi câu trả lời của Jon Skeet, gần đây tôi đã gặp phải trường hợp tôi cần triển khai phương thức hashCode chỉ với một tập con của các trường được sử dụng trong phương thức equals. Kịch bản (được đơn giản hóa) là:
Tôi có hai lớp A
và B
mỗi trường có chứa tham chiếu đến phần khác ngoài việc có một khóa Chuỗi được xác định. Sử dụng hashCode tự động và bằng máy phát điện trong Eclipse (trong đó, không giống như Netbeans, chỉ cung cấp cho các tùy chọn để sử dụng các lĩnh vực tương tự ở cả hai phương pháp) Tôi kết thúc với các lớp sau:
public class A {
public B b;
public String bKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((b == null) ? 0 : b.hashCode());
result = prime * result + ((bKey == null) ? 0 : bKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof A))
return false;
A other = (A) obj;
if (b == null) {
if (other.b != null)
return false;
} else if (!b.equals(other.b))
return false;
if (bKey == null) {
if (other.bKey != null)
return false;
} else if (!bKey.equals(other.bKey))
return false;
return true;
}
}
public class B {
public A a;
public String aKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((aKey == null) ? 0 : aKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof B))
return false;
B other = (B) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (aKey == null) {
if (other.aKey != null)
return false;
} else if (!aKey.equals(other.aKey))
return false;
return true;
}
}
vấn đề này được đưa ra về khi tôi đã cố gắng để thêm class A đến một HashSet theo cách sau:
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
Set<A> aSet = new HashSet<A>();
aSet.add(a);
}
này sẽ kết thúc trong một StackOverflowError kể từ khi thêm a
để aSet
sẽ dẫn đến a
'phương thức hashCode s được gọi, mà sẽ dẫn đến b
' s hashCode
là gọi là, sẽ r esult trong số 's hashCode
được gọi, v.v. v.v.Cách duy nhất để giải quyết vấn đề này là xóa tham chiếu đến A
từcủa hashCode
và equals
HOẶC chỉ bao gồm String bKey
trong phương thức hashCode của B
. Vì tôi muốn phương pháp B.equals
để bao gồm tham chiếu A trong việc kiểm tra tính bình đẳng, điều duy nhất tôi có thể làm là làm cho B.hashCode
chỉ sử dụng một tập con của các trường được sử dụng trong B.equals
tức là chỉ sử dụng B.bKey
trong B.hashCode
. Tôi không thể nhìn thấy cách nào khác.
Có thể thiết kế của tôi bị thiếu sót và tôi chào mừng ai đó chỉ ra điều đó nhưng về cơ bản là cách đối tượng tên miền của tôi được cấu trúc trong chương trình thực tế của tôi.
Với hàm ý rằng trình tạo mã Netbeans là sai để đưa ra lựa chọn nếu không bao giờ có lý do chính đáng để chọn các trường khác nhau. – Raedwald