Wednesday, April 06, 2005

ใช้ commons.lang ช่วยเขียน hashCode, equals Method

ใครที่เคยเขียน Java Object จะพบว่า
ในบาง use case จำเป็นต้องมีการ overide equals กับ hashCode method
(ปกติใน object ที่เราไม่ได้ implement equals method
ความหมายของ equals ก็คือดูว่าเป็น instance เดียวกันหรือไม่
แต่ถ้าเราต้องการเปลี่ยนความหมายของ equals
ให้เป็นในลักษณะว่า property ทุกๆตัวเท่ากันหรือไม่แทน
ก็ต้อง override equals method ซึ่ง java object มี
constrain ว่าถ้าเรา overide equals method เมื่อไร
ก็ควรจะต้อง override hashCode method ด้วย
)

การเขียน method 2 อันนี้เราสามารถใช้
jakarta-commons-lang เข้ามาช่วยได้ โดยใช้ class
  • HashCodeBuilder
  • EqualsBuilder
ตัวอย่างการใช้งานกรณี hashCode
public class Person {
String name;
int age;
boolean isSmoker;
...

public int hashCode() {
// you pick a hard-coded, randomly chosen, non-zero, odd number
// ideally different for each class
return new HashCodeBuilder(17, 37).
append(name).
append(age).
append(smoker).
toHashCode();
}
}

หรือจะใช้ reflection แทนก็ได้
  public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}

ส่วนกรณี equals ก็เช่นเดียวกัน
  public boolean equals(Object o) {
if ( !(o instanceof MyClass) ) {
return false;
}
MyClass rhs = (MyClass) o;
return new EqualsBuilder()
.appendSuper(super.equals(o))
.append(field1, rhs.field1)
.append(field2, rhs.field2)
.append(field3, rhs.field3)
.isEquals();
}
ถ้าใช้ reflection
  public boolean equals(Object o) {
return EqualsBuilder.reflectionEquals(this, o);
}

ส่วนใครที่ใช้ Eclipse ถ้าอยากให้ชีวิตง่ายขึ้นกว่านี้อีก
ก็ต้องใช้ Commonclipse ซึ่งมี plugin ที่ช่วย generate
method ให้อีกที (ใช้ common lang builder เหมือนกัน)

Note: กรณีที่ใช้ hibernate มักจะมี
ข้อสงสัยว่าเราควรจะ override equals และ hashCode หรือไม่
ในกรณี use case ปกติ เราไม่จำเป็นต้อง override equals หรือ hashCode
เราจะ override ต่อเมื่อ
- it is a used as a composite primary key class
- instances of that class, loaded in different Hibernate Sessions, are in the same Set (or should be compared)
ส่วนรูปแบบการ implement ปกติจะใช้
    public boolean equals(Object other) {
if ( !(other instanceof Client) ) return false;
Client castOther = (Client) other;
return new EqualsBuilder()
.append(this.getId(), castOther.getId())
.isEquals();
}
// Note: id is object id (surrogate identifier) of this object

public int hashCode() {
return new HashCodeBuilder()
.append(getId())
.toHashCode();
}

สถานะการณ์จะยุ่งยากขึ้นอีกถ้ามีการ compare proxy object กับ real object
อ่านเพิ่มเติมการถกเถึยงประเด็นเหล่านี้ได้ที่ this forum

Related link from Roti

No comments: