เมื่อเปรียบเทียบอ็อบเจ็กต์ใน Java คุณทำการตรวจสอบความหมายเปรียบเทียบประเภทและสถานะการระบุอ็อบเจ็กต์กับ:
- ตัวเอง (เช่นเดียวกัน)
- ตัวเอง (โคลนหรือสำเนาที่สร้างขึ้นใหม่)
- วัตถุอื่น ๆ ประเภทต่างๆ
- วัตถุอื่น ๆ ประเภทเดียวกัน
null
กฎ:
- สมมาตร :
a.equals(b) == b.equals(a)
equals()
มักจะมีอัตราผลตอบแทนtrue
หรือfalse
แต่ไม่เคยNullpointerException
, ClassCastException
หรือ Throwable อื่น ๆ
เปรียบเทียบ:
- การตรวจสอบประเภท : อินสแตนซ์ทั้งสองต้องเป็นประเภทเดียวกันหมายความว่าคุณต้องเปรียบเทียบคลาสจริงเพื่อความเท่าเทียมกัน นี้มักจะไม่ได้ดำเนินการอย่างถูกต้องเมื่อนักพัฒนาใช้
instanceof
สำหรับการเปรียบเทียบชนิด A extends B -> a instanceof b != b instanceof a)
(ซึ่งจะทำงานเฉพาะตราบใดที่ไม่มีการย่อยและละเมิดกฎสมมาตรเมื่อ
- การตรวจสอบความหมายของสถานะการระบุ : ตรวจสอบว่าคุณเข้าใจว่าอินสแตนซ์ระบุสถานะใด บุคคลอาจถูกระบุโดยหมายเลขประกันสังคม แต่ไม่ระบุด้วยสีผม (สามารถย้อมได้) ชื่อ (สามารถเปลี่ยนแปลงได้) หรืออายุ (เปลี่ยนแปลงตลอดเวลา) เฉพาะกับออบเจ็กต์ค่าคุณควรเปรียบเทียบสถานะเต็ม (ฟิลด์ที่ไม่ใช่ชั่วคราวทั้งหมด) มิฉะนั้นให้ตรวจสอบเฉพาะสิ่งที่ระบุอินสแตนซ์
สำหรับPerson
ชั้นเรียนของคุณ:
public boolean equals(Object obj) {
// same instance
if (obj == this) {
return true;
}
// null
if (obj == null) {
return false;
}
// type
if (!getClass().equals(obj.getClass())) {
return false;
}
// cast and compare state
Person other = (Person) obj;
return Objects.equals(name, other.name) && Objects.equals(age, other.age);
}
คลาสยูทิลิตี้ทั่วไปที่ใช้ซ้ำได้:
public final class Equals {
private Equals() {
// private constructor, no instances allowed
}
/**
* Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state
*
* @param instance object instance (where the equals() is implemented)
* @param other other instance to compare to
* @param stateAccessors stateAccessors for state to compare, optional
* @param <T> instance type
* @return true when equals, false otherwise
*/
public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) {
if (instance == null) {
return other == null;
}
if (instance == other) {
return true;
}
if (other == null) {
return false;
}
if (!instance.getClass().equals(other.getClass())) {
return false;
}
if (stateAccessors == null) {
return true;
}
return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other)));
}
}
สำหรับPerson
ชั้นเรียนของคุณโดยใช้คลาสยูทิลิตี้นี้:
public boolean equals(Object obj) {
return Equals.as(this, obj, t -> t.name, t -> t.age);
}