網頁

2014年1月7日 星期二

Effective Java實作equals()

equals()這個方法,定義在Object class中,這個是所有class的base class,因此所有的class都繼承這個方法,預設是比較內存位址,不過Mix需要的是商務邏輯上的比較,所以會覆寫equals()。





預設是比較兩個object的reference 是否相等,就如先前的test case,Mix建構了兩個RoleImpl,然後role.equals(role2)傳回false,因為這兩個物件不是同reference ,故為flase。

不過實務上,Mix的商務邏輯是還要判斷id是否相等,而不只是判斷reference,通常這類的class稱之為valuse class,因此需要覆寫equals(),來滿足實務上的需求。

如果有使用ORM,如:Hibernate,有些field有可能會延遲加載,造成不正確,因此改成getter來取值。還記得test method嗎?比較role與role2是否相等,用商務邏輯id值來比較。

 /*
  * (non-Javadoc)
  *
  * @see java.lang.Object#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  RoleImpl other = (RoleImpl) obj;
  // if (id != other.id)
  if (getId() != other.getId())
   return false;
  return true;
 }






覆寫equals()之後,Mix執行一次測試方法equals(),來查看其結果。

 /**
  * Equals.
  */
 @Test
 public void equals() {
  Role role = new RoleImpl();
  role.setId(1);
  //
  Role role2 = new RoleImpl();
  role2.setId(1);
  //
  System.out.println(role.getId() + ", " + role2.getId());
  
  boolean result = role.equals(role2);
  System.out.println(result);
  // 尚未覆寫equals時,會測試失敗
  assertTrue(result);
 }






這次測試成功了,不但覆寫equals()滿足了我們商務邏輯的需求,同時也滿足了TDD所提倡的精神。




console查看其結果。

1
OpenYu
100
2
1, 1
true
1
OpenYu
100





另一種用TestNG的測試結果,最終結果都是測試成功,但工具不同,輸出的畫面略有不同。




console查看其結果。

[TestNG] Running:
1
OpenYu
100
2
1, 1
true
1
OpenYu
100
PASSED: clonez
PASSED: equals
PASSED: setter

===============================================
    Default test
    Tests run: 3, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@2c41d05d: 162 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@2fb3f8f6: 61 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@32ef2c60: 17 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@6fb000e7: 11 ms
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@3f77b3cd: 11 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms






當然也可以利用IDE如:Eclipse所提供的自動產生代碼,來覆寫equals()。

RoleImpl上點右鍵 Source -> Generate hashCode() and equals()...。




或是利用Apache Commons EqualsBuilder來覆寫。

 /*
  * (non-Javadoc)
  * 
  * @see java.lang.Object#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object obj) {
  if (!(obj instanceof RoleImpl)) {
   return false;
  }
  RoleImpl other = (RoleImpl) obj;
  return new EqualsBuilder().append(getId(), other.getId()).isEquals();
 }





  1. Effective Java Item 8:覆寫equals()。



沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...