2012-02-13 6 views
10

私はhibernateを使用しており、equalsとhashCode()をオーバーライドする必要があります。私はgoogle-guavaのequalsとhashCodeヘルパーを使うことにしました。Google Guavaを使用してequalsとhashCodeを正しく実装しましたか?

ここに何か不足しているかどうかを知りたいと思っていました。

私はidImageのファイルパスの取得/設定メソッドを持っています。

@Entity 
@Table(name = "IMAGE") 
public class ImageEntity { 
    private Integer idImage; 
    private String filePath; 

    @Override 
    public int hashCode() { 
     return Objects.hashCode(getFilePath()); 
    } 

    @Override 
    public boolean equals(final Object obj) { 
     if(obj == this) return true; 
     if(obj == null) return false; 

     if(obj instanceof ImageEntity){ 
      final ImageEntity otherImage = (ImageEntity) obj; 
      return Objects.equal(getFilePath(), otherImage.getFilePath()); 
     } 
     return false; 
    } 
} 

EDIT:

は、継承に走ったとあるようhere

+0

それは右に見える...あなたはそれで何らかのエラー/不要な動作を得ていますか? – Marcelo

+0

@NimChimpsky idImageは、データベース内の主キーの自動インクリメント(hibernateを使用)へのIDマッピングです。 – brainydexter

+0

@Marceloいいえ、現在ではありません。すべてがうまくいく。私は何かを逃したかどうかを知りたかっただけです。 – brainydexter

答えて

18

演算子instanceofの問題点は、多形性を考慮して動作することです。

のは、あなたが行うこと、例えば、言ってみましょう。この:その後、

public class AdvancedImageEntity extends ImageEntity 
{ 
    //some code here 
} 

、あなた行い、この:名前が示唆

ImageEntity ie = new ImageEntity(); 
AdvancedImageEntity advanced_ie = new AdvancedImageEntity(); 

boolean this_will_be_true = ie.equals (advanced_ie); 

として、equals呼び出しが理由で、trueを返すということinstanceofオペレータ。

私はこれが基本的なもののように聞こえ、ほとんどの人はそれを知っていますが、それを忘れるのは簡単です。今、あなたがその行動を望むなら、うまくいって、equalsを正しく実装しました。しかし、あなたはImageEntityオブジェクトは、その後finalであるかについてinstanceofを忘れて、このようなあなたのequals方法を実装するためにImageEntityを宣言いずれか、(架空の)AdvancedImageEntityオブジェクトと等しいあってはならないことを考慮した場合:これはチェックします

を参照のタイプにかかわらず、オブジェクトの真の型です。 objパラメータがサブクラスのインスタンスである場合、instanceofによって「スリップ」します。しかしgetClassはもっと厳しく、許可されません。

PS:私はinstanceofが悪いと言っているわけではありません。使用しないでください。私はちょうどあなたがこの特定の状況を認識し、これを考慮に入れて使用するかどうかを決定しなければならないと言っています。

+0

+1。 instanceofの洞察に感謝します。 – brainydexter

+1

さらに良い - DTOをサブクラス化しない – Ray

+0

@Ray DTOとは何ですか? –

3

にその罰金をサンプルを持っています。 instanceofはヌルチェックを不自然にします。

また、私はこのIDはverydebatableですが、自動生成されたIDを使用しても問題ありません。

+0

私はヌルチェックの冗長性について同意します。それを取り除くだけでOKです。 –

+0

また、 'Objects.hashCode(getFilePath())'の代わりに 'getFilePath()。hashCode()'を使うだけでいいです。 –

+0

@LouisWasserman - 'getFilePath()'が 'null'を返すことができれば失敗します。ドキュメントには言及されていませんが、 'Arrays.hashCode()'を呼び出す 'Objects.hashCode()'が 'null'値を安全に処理すると思われます。 –

12

あなたは実際にあなたのequalsとhashCodeの実装をテストするためにGuava EqualsTesterを使用することができます。

new EqualsTester() 
    .addEqualityGroup("hello", "h" + "ello") 
    .addEqualityGroup("world", "wor" + "ld") 
    .addEqualityGroup(2, 1 + 1) 
    .testEquals(); 

これは、グアバTESTLIBにあります。

<dependency> 
    <groupId>com.google.guava</groupId> 
    <artifactId>guava-testlib</artifactId> 
    <scope>test</scope> 
</dependency> 

実装にマイナーチェンジ:

@Override public boolean equals(final Object obj) { 
    if(obj == this) return true; 
    return obj instanceof ImageEntity && 
     Objects.equal(getFilePath(), ((ImageEntity) obj).getFilePath()); 
} 
+0

+1。 guava equalsTesterへのリンクありがとう! – brainydexter

+0

@Davidあなたの主張を理解していない。 –

+0

@Davidこれは失敗すると思いますが、これはこの例では明らかです。 –

関連する問題