自動化hashCode()和equals()
? 問題產生:當需要自動實現hashCode()和equals()方法
? 解決方法:使用EqualsBuilder和HashCodeBuilder
? 使用舉例:
?
import
?org.apache.commons.lang.builder.HashCodeBuilder;
import
?org.apache.commons.lang.builder.EqualsBuilder;


public
?
class
?PoliticalCandidate?
{
????
//
?Member?variables?-?omitted?for?brevity
????
//
?Constructors?-?omitted?for?brevity
????
//
?get/set?methods?-?omitted?for?brevity
????
//
?A?hashCode?which?creates?a?hash?from?the?two?unique?identifiers
????
public
?
int
?hashCode(?)?
{
????????
return
?
new
?HashCodeBuilder(
17
,?
37
)
???????????????????????.append(firstName)
???????????????????????.append(lastName).toHashCode(?);
????}
????
//
?An?equals?which?compares?two?unique?identifiers
????
public
?
boolean
?equals(Object?o)?
{
????????
boolean
?equals?
=
?
false
;

????????
if
?(?o?
!=
?
null
?
&&
PoliticalCandidate.
class
.isAssignableFrom(o)?)?
{
????????????PoliticalCandidate?pc?
=
?(PoliticalCandidate)?o;
????????????equals?
=
?(
new
?EqualsBuilder(?)
???????????????????????.append(firstName,?ps.firstName)
???????????????????????.append(lastName,?ps.lastName)).isEquals(?);
????????}
????????
return
?equals;
????}
}
Discussion:
1.在上述例子中,當有相同的firstname和lastname時,認為兩個對象的hashCode相同,從而equals()返回true.
如果hashCode取決于該class的所有filed時需要使用反射機制來產生一個hashCode。
public
?
int
?hashCode(?)?
{
????
return
?HashCodeBuilder.reflectionHashCode(
this
);
}
和ToStringBuilder?與 HashCodeBuilder一樣EqualsBuilder 也是使用append()方法進行配置,
EqualsBuilder的append()方法可以接受基本類型、對象、數組作為參數。EqualsBuilder強大的地方在于可以直接把數組作為參數傳入append()方法,EqualsBuilder會依次比較數組中的每個元素。
2.如果兩個對象相等當且僅當每個屬性值都相等 這句話可以由以下代碼實現:
public
?
boolean
?equals(Object?o)?
{
????
return
?EqualsBuilder.reflectionEquals(
this
,?o);
}
問題提出:需要快速實現compareTo()方法
解決方法:使用CompareToBuilder提供的compareTo()方法。同樣的CompareToBuilder也使用了反射機制。以下代碼提供了一個compareTo()方法,用于比較兩個對象所有的非static和非transient成員變量。
import
?org.apache.commons.lang.builder.CompareToBuilder;

//
?Build?a?compareTo?function?from?reflection?
public
?
int
?compareTo(Object?o)?
{
????
return
?CompareToBuilder.reflectionCompare(
this
,?obj);

}
Discussion:
CompareToBuilder.reflectionCompare()提供了兩個對象non-static和nontransient成員變量的方法。 reflectionCompare()方法不予理會static和transient變量,因此以下代碼中的averageAge和fullName變量是不會進入比較表達式的。
public
?
class
?PoliticalCandidate?
{
????
//
?Static?variable
????
private
?
static
?String?averageAge;

????
//
?Member?variables?
????
private
?String?firstName;
????
private
?String?lastName;

????
private
?
transient
?String?fullName;
????
//
?Constructors
????
//
?get/set?methods
????
//
?Build?a?compareTo?function?from?reflection?
????
public
?
int
?compareTo(Object?o)?
{
????????
return
?CompareToBuilder.reflectionCompare(
this
,?obj);
????}
}
比較對象成員變量的時候應該有一個比較的次序存在,上述代碼中默認的應該是先比較lastName,然后是firstName。調用append()方法可以把要比較的變量加入比較表達式中,并且遵循后加入的先比較的次序。
例如:
public
?
int
?compareTo(Object?o)?
{
????
int
?compare?
=
?
-
1
;?
//
?By?default?return?less-than
????
if
(?o?
!=
?
null
?
&&
?PoliticalCandidate.
class
.isAssignableFrom(?o.getClass(?)?)?)?
{

????????????PoliticalCandidate?pc?
=
?(PoliticalCandidate)?o;
????????????compare?
=
?(
new
?CompareToBuilder(?)
??????????????????????????.append(firstName,?pc.firstName)
??????????????????????????.append(lastName,?pc.lastName)).toComparison(?);
????}
????
return
?compare;
}
在比較的時候會先比較lastName,只有在lastName相同的情況下才會比較firstName。
ps:實現compareTo()的時候應保證和equals()規則相同,即當compareTo()返回是0的時候equals()應該返回true。
本筆記是在閱讀Jakarta Commons Cookbook時所留下的。
1.使用ReflectionToStringBuilder 或者ToStringBuilder 自動產生toString()的內容。
?? 使用舉例:假設有一個表征校長候選人信息的javabean-PoliticalCandidate。
??

public?class?PoliticalCandidate?
{
????private?String?lastName;
????private?String?firstName;
????private?Date?dateOfBirth;
????private?BigDecimal?moneyRaised;
????private?State?homeState;

????//?get/set方法省略

????public?void?toString(?)?
{
????????ReflectionToStringBuilder.toString(?this?);
????}
}
該bean里面有個toString()方法,假設有以下操作:
//?Create?a?State
State?va?=?new?State(?"VA",?"Virginia");

//?Create?a?Birth?Date
Calendar?calendar?=?new?GregorianCalendar(?);
calendar.set(?Calendar.YEAR,?1743?);
calendar.set(?Calendar.MONTH,?Calendar.APRIL?);
calendar.set(?Calendar.DAY_OF_MONTH,?13?);
Date?dob?=?calendar.getTime(?);

BigDecimal?moneyRaised?=?new?BigDecimal(?293829292.93?);????????

//?Create?a?Political?Candidate
PoliticalCandidate?candidate?=?
????new?PoliticalCandidate(?"Jefferson",?"Thomas",?dob,?moneyRaised,?va?);
?????
System.out.println(?candidate?);

假設State對象也是一個使用ReflectionToStringBuilder的javabean,上述程序一種可能的輸出為com.discursive.jccook.lang.builders.PoliticalCandidate@187aeca
??? [lastName=Jefferson,\firstName=Thomas,
???? dateOfBirth=Sat Apr 13 22:38:42 CST 1743,
???? moneyRaised=\293829292.930000007152557373046875,
???? state=\com.discursive.jccook.lang.builders.State@87816d
???????? [abbreviation=VA,name=Virginia]]
org.apache.commons.lang.builder
CompareToBuilder – 用于輔助實現Comparable.compareTo(Object)方法;
EqualsBuilder – 用于輔助實現Object.equals()方法;
HashCodeBuilder – 用于輔助實現Object.hashCode()方法;
ToStringBuilder – 用于輔助實現Object.toString()方法;
ReflectionToStringBuilder – 使用反射機制輔助實現Object.toString()方法;
ToStringStyle – 輔助ToStringBuilder控制輸出格式;
StandardToStringStyle – 輔助ToStringBuilder控制標準格式。
posted on 2007-01-23 09:07
???MengChuChen 閱讀(8065)
評論(0) 編輯 收藏 所屬分類:
JavaBasic