自动化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变量是不会进入比较表达式的。
<-----------------------------
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想
用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient 型的变量是被包括进去的。
-------------------------------->
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;
}
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
在比较的时候会先比较lastName,只有在lastName相同的情况下才会比较firstName。 ps:实现compareTo()的时候应保证和equals()规则相同,即当compareTo()返回是0的时候equals()应该返回true。
ReflectionToStringBuilder
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控制标准格式。