2005/02
ValueObject(値を格納するオブジェクト)でフィールドの数が多かったりすると
equals(),compareTo(),toString()なんかのメソッドを実装するのって
めんどくさいですよね?これらをリフレクションで自動的に実装してくれる
機能がcommons.lang.builderパッケージです。これらを呼び出すコードを共通化
したスーパークラスを作りました。
じゃあソース見てちょーだい
package jp.gr.java_conf.yamarou.util; import java.io.Serializable; import org.apache.commons.lang.builder.CompareToBuilder; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** * 値オブジェクトの基本的な機能を提供する。 * 値オブジェクトは等クラスを継承するだけで値オブジェクトとしての機能を持つ。 * @author yamarou */ public class ValueObject implements Serializable, Comparable { /** * オブジェクトの文字列表現を返します。 * @return obj このオブジェクトの文字列表現 */ public String toString() { return ToStringBuilder.reflectionToString(this); } /** * このオブジェクトと他のオブジェクトが等しいかどうかを示します。 * @param obj 比較対象の参照オブジェクト * @return obj 引数に指定されたオブジェクトとこのオブジェクトが等しい場合は * true、そうでない場合は false */ public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); } /** * このオブジェクトと指定されたオブジェクトの順序を比較します。 * @param obj 比較対象の Object * @return このオブジェクトが指定されたオブジェクトより小さい場合は * 負の整数、等しい場合はゼロ、大きい場合は正の整数 */ public int compareTo(Object obj) { return CompareToBuilder.reflectionCompare(this, obj); } /** * オブジェクトのハッシュコード値を返します。 * @return このオブジェクトのハッシュコード値 */ public int hashCode() { System.out.print("super.hashCode()=" + super.hashCode() + "★"); return HashCodeBuilder.reflectionHashCode(this); } } /** * サンプルのValueObject * @author yamarou */ class UserVO extends ValueObject { private String name; private String bloodType; /** * @return */ public String getBloodType() { return bloodType; } /** * @return */ public String getName() { return name; } /** * @param string */ public void setBloodType(String string) { bloodType = string; } /** * @param string */ public void setName(String string) { name = string; } public static void main(String[] args) { UserVO obj = new UserVO(); obj.setBloodType("B"); obj.setName("tanaka"); System.out.println("obj.toString()=" + obj.toString()); System.out.println(""); UserVO obj2 = new UserVO(); obj2.setBloodType("B"); obj2.setName("tanaka"); System.out.println("obj.equals(obj2)=" + obj.equals(obj2)); System.out.println("obj.compareTo(obj2)=" + obj.compareTo(obj2)); System.out.println("obj.hashCode()=" + obj.hashCode()); System.out.println("obj2.hashCode()=" + obj2.hashCode()); System.out.println( "((Object) obj).hashCode()=" + ((Object) obj).hashCode()); System.out.println( "((Object) obj2).hashCode()=" + ((Object) obj2).hashCode()); System.out.println(""); obj2.setBloodType("A"); System.out.println("obj.equals(obj2)=" + obj.equals(obj2)); System.out.println("obj.compareTo(obj2)=" + obj.compareTo(obj2)); System.out.println("obj.hashCode()=" + obj.hashCode()); System.out.println("obj2.hashCode()=" + obj2.hashCode()); System.out.println( "((Object) obj).hashCode()=" + ((Object) obj).hashCode()); System.out.println( "((Object) obj2).hashCode()=" + ((Object) obj2).hashCode()); System.out.println(""); obj2.setBloodType("O"); System.out.println("obj.compareTo(obj2)=" + obj.compareTo(obj2)); } }
[実行結果]
obj.compareTo(obj2)=0
super.hashCode()=1211499742★obj.hashCode()=-881004887
super.hashCode()=931906782★obj2.hashCode()=-881004887
super.hashCode()=1211499742★((Object) obj).hashCode()=-881004887
super.hashCode()=931906782★((Object) obj2).hashCode()=-881004887
obj.equals(obj2)=false
obj.compareTo(obj2)=1
super.hashCode()=1211499742★obj.hashCode()=-881004887
super.hashCode()=931906782★obj2.hashCode()=-881004924
super.hashCode()=1211499742★((Object) obj).hashCode()=-881004887
super.hashCode()=931906782★((Object) obj2).hashCode()=-881004924
obj.compareTo(obj2)=-13
とちゃんと結果を返します。でもhashCodeはjava.lang.Object#hashCodeは
同じ値を持ってても違うインスタンスの場合、違うhashCodeを返すけど
HashCodeBuilder.reflectionHashCode(this)だと同じhashCodeを返すから
どっちがいいんだかって感じですねぇ。あとcompareToもどういう順序で
比較していってるかがよく分からないから自分で実装したほうがいいかも
しれないですね。toString()とequals()は使えそうですね♪