2017-01-31 9 views
0

基本情報: 私はMyCustomObjectを生成するMyCustomObjectGeneratorを持っています。このオブジェクトは、常に同じ値で作成されます。このオブジェクトにはmutchコード、インタフェース、列挙型、サブクラスが含まれていますので、ここでは簡単に説明します。インタフェースのすべてのオブジェクトまたは実装は、等しく& hashCodeメソッドをオーバーライドします(うまくいけば正しい方法で)。Java hashCode()は同じオブジェクト作成の異なる実行で異なります

このMyCustomObjectは、カスタムシリアライザを使用して、ジャクソンと共にJSONにシリアル化されます(MyCustomObjectには、ジャクソンの注釈のようなジャクソンの依存関係は含まれていません)。

各JSONは、MyCustomObjectのhashCode(以下のコードを参照)に基づいて計算されたIDを取得します。このidは、同じjsonsを非常に高速に識別するためのチェックサムとしてのみ使用されます。 UUIDに基づいた別のIDがあり、ジョブ自体を識別します。したがって、2つのジョブが同じチェックサムを持つことができます。

問題: JSONを生成し、ファイルから事前に定義されたJSONと、このJSONをチェック2のJUnitテスト(1つのJUnitの-TestClassを最小限で&最大の方法は)あります。両方のテスト/メソッドを実行すると、JSONはファイルのものと一致しますが、testMaximal()メソッドを実行するだけで、生成されたIDが同じでないためアサーションが失敗します。したがって、hashCodeは異なるようです。 2つのテストメソッドを再び開始すると、jsonsはファイルからのものと再び一致するため、生成されたオブジェクトにはZonedDateTime.now()のようなランダムなコンテンツは含まれません。他のJSON値は常に同じで、IDだけが異なります。 HashCodeは実行(2メソッド/ 1メソッド)条件が同じであれば同じであるが、この実行条件を変更すると異なる。これは私にとって本当に奇妙です。

ここで、どのクラスがhashCodeメソッドを正しくオーバーライドしない(または異なるhashCodeを生成する)かを評価する必要があります(idは含まれているすべてのオブジェクトのhashCodesに基づいています)。誰かが、Reflectionを介してMyCustomObjectの各オブジェクト、変数、サブクラス、インターフェースのhashCodeを印刷する良いアイデアを持っていますか?既に試しました

ReflectionToStringBuilder.toString(myCustomObject, ToStringStyle.DEFAULT_STYLE) 

しかし、これはmyCustomObjectの各サブサブ要素のhashCodeを出力しません。

正確なオブジェクト値を含めることができます。 hashValue、次に私はそれを比較することができます。

ReflectionToStringBuilder.toString()で異なる1つのオブジェクトが見つかりましたが、このオブジェクト自体にはmutchインターフェイス、変数などが含まれていますが、このBlablaObject @ 4fb64261 [...]の値はすべて同じです。ハッシュコードは、トップ問題について

が欠落しています。 がありますが知ら場合、またはSTH「あなたはHashMapの中でキーとして列挙型を使用する場合、ハッシュコードは、JavaスタックまたはJVMのバージョンに依存します」のようなのhashCode()が奇妙に振る舞うこと。そうですね。


CODE

MyCustomObjectGeneratorの.javaファイル

public class MyCustomObjectGenerator { 

    private MyCustomObject(){}; 

    public static MyCustomObject generate(boolean isMinimal){ 
     //if minimal then create minimal object 
     //if minimal == false then create maximized object**strong text** 
     MyCustomObject myCustomObject = new MyCustomObject(...); 
     myCustomObject.setXY(...) 
     ... 
     return myCustomObject; 
    } 
} 

MyCustomObject。Javaの

import javax.xml.bind.DatatypeConverter; 
import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import org.apache.commons.lang3.builder.HashCodeBuilder; 
import org.apache.commons.lang3.builder.EqualsBuilder; 

public class MyCustomObject { 
    //variables, enums, interface ... here 
    ...  
    public MyCustomObject(...){...} 

    //mutch code here 
    ... 

    public String getChecksum() { 
     String id = Integer.toString(hashCode()); 
     try { 
      MessageDigest md = MessageDigest.getInstance("MD5"); 
      byte[] digest = md.digest(id.getBytes("UTF-8")); 
      id = DatatypeConverter.printHexBinary(digest); 
     } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { 
      // do nothing here 
     } 
     return new id; 
    } 

    @Override 
    public int hashCode() { 
     return new HashCodeBuilder(-1013166723, 372138085) 
     //if needed in extended classes: .appendSuper(super.hashCode()) 
     .append(...) 
     .... 
     .toHashCode(); 
    } 

    @Override 
    public boolean equals(
      final Object other) { 
     if (!(other instanceof MyCustomObject)) { 
      return false; 
     } 
     MyCustomObject castOther = (MyCustomObject) other; 
     return new EqualsBuilder() 
      // if needed in extended classes: .appendSuper(super.hashCode()) 
      .append(..., ...) 
      .... 
      .isEquals(); 
    } 
} 
+1

EnumのデフォルトのhashCode()はsuper.hashCode()(java.lang.Objectの実装)として定義されているため、各JVMインスタンスごとに異なります。 HashCodeコントラクトは次のように述べています。「この整数は、あるアプリケーションの実行から同じアプリケーションの別の実行まで一貫している必要はありません。だから、あなたはそれを持っていると思います:enumsの場合でも、すべてのhashCode()メソッドをオーバーライドしてJVMインスタンス全体の安定性を保証するか、各インスタンスごとにハッシュ値が異なるかのどちらかです。 – GPI

答えて

2

hashCode()によって返される値は、アプリケーションの実行ごとに異なります。これには含まれています:

  • すべての配列型
  • すべてenum種類のオブジェクトの平等とオブジェクトIDは同じものです
  • 多くの他のタイプ。例えばObject,クラス,スレッド, StringBuilder / StringBuffer`です。一般的なルールとして

、JavaのSEによりとして定義されたクラスがObject.equals(Object)からのセマンティクスが異なるequalsメソッドを持つものとしてを文書化されていない場合は、それがまたObject.hashCode()を使用することを前提とし...とその必要がありますハッシュコードは実行ごとに異なります。

1

はあなたがハッシュベースのデータ構造で選ぶバケットを除いhashCode()を使用することになっていません。あなたが見つけたように、それは確かに検証の場所を持っていません。

関連する問題