JAva学習:ObjectクラスequalsとhashCodeメソッド

4177 ワード

文章を書き始める前に、いくつかの問題を考えなければなりません.
  • equalsとhashCodeの方法は何ですか?
  • equalsメソッドにはどのような特性がありますか?
  • equalsとhashCodeの間の共通の約束
  • 1.equalsとhashCodeの方法は何ですか.
    equalメソッドは、1つのオブジェクトが別のオブジェクトに等しいかどうかを検出するために使用されます.Objectクラスでは、このメソッドは、2つのオブジェクトが同じ参照を持っているかどうかを判断します.2つのオブジェクトが同じ参照を持っている場合、それらは等しいに違いありません.しかし、多くのクラスでは、このような判断は意味がなく、2つのオブジェクトの状態の等化を検出することがしばしば必要であり、2つのオブジェクトの状態が等しければ、この2つのオブジェクトは等化していると考えられる.そのため、ビジネス上のニーズを満たすためにequalsメソッドを書き換える必要があります.次に、デフォルトのequalsメソッドの実装を示します.
    public boolean equals(Object obj) {
        return (this == obj);
    }

    hashCodeメソッドは、オブジェクトから導出される整数値(ハッシュコード)です.ハッシュコードが不規則です.Objectクラスでは、デフォルトのハッシュコードがオブジェクトの格納アドレスです.
    2.equalsメソッドにはどのような特性がありますか?
    Java言語仕様では、equalsメソッドには次の特性が必要です.
  • 自己反転:任意の非空参照xに対して、x.equals(x)はtrueを返すべきである.
  • 対称性:任意の参照xおよびyについて、y.equals(x)がtrueを返す場合にのみ、x.equals(y)もtrueを返すべきである.
  • 伝達性:x、y、zを参照する場合、 x.equals(y)はtrueを返し、y.equals(z)はtrueを返し、x.equals(z)もtrueを返すべきである.
  • コンシステンシ:xとyが参照するオブジェクトが変化しない場合は、繰り返し呼び出します. x.equals(y)は同じ結果を返すべきである.
  • 任意の非空参照xに対して、x.equals(null)はfalseを返すべきである.

  • 3.equalsとhashCode間の共通の約束
    Object.hashCodeの共通の約束を見てみましょう.
  • アプリケーションの実行中に、オブジェクトのequalsメソッドを比較するために使用される情報が変更されていない場合、オブジェクトに対してhashCodeメソッドが複数回呼び出され、同じ整数を一貫して返さなければならない.同じアプリケーションの複数回の実行中に、この整数は異なる場合があります.すなわち、このアプリケーションが今回実行した整数と、次の実行で返される整数とは一致しない場合があります.
  • equals(Object)メソッドに従って2つのオブジェクトが等しい場合、2つのオブジェクトのいずれかを呼び出すhashCodeメソッドは、同じ整数結果を生成する必要があります.
  • equals(Object)メソッドに従って2つのオブジェクトが等しくない場合、2つのオブジェクトのいずれかを呼び出すhashCodeメソッドは、異なる整数結果を生成する必要はありません.しかしながら、プログラマは、等しくないオブジェクトに対して異なる整数結果を生成し、ハッシュテーブルの性能を向上させる可能性があるという事実を認識すべきである.

  • equalsメソッドを再定義する場合は、hashCodeメソッドを再定義して、ユーザーがオブジェクトをハッシュ・リストに挿入できるようにする必要があります.
    拡張
    次に、equalsメソッドを記述するための推奨事項を示します.
  • には、パラメータ名がotherObjectと表示され、後でotherという別の変数に変換する必要があります.
  • thisとotherObjectが同じオブジェクトを参照しているかどうかを検出します.
  • otherObjectがnullであるかどうかを検出し、nullである場合falseを返します.この検査は必要だ.
  • thisとotherObjectが同じクラスに属しているかどうかを比較します.equalsの意味が各サブクラスで変更された場合、getClassで検出されます.すべてのサブクラスが統一された意味を持っている場合はinstanceofで検出されます.
  • otherObjectを対応するクラスタイプ変数に変換します.
  • では、比較が必要なすべてのドメインの比較が開始されます.==を使用して基本タイプドメインを比較し、equalsを使用してオブジェクトドメインを比較します.サブクラスでequalsを再定義する場合は、呼び出しsuper.equalsを含めます.
  • public class Employee {
    
        @Override
        public boolean equals(Object otherObject) {
            // 2
            if(this == otherObject) return true;
            // 3
            if(otherObject == null) return false;
            // 4
            //if(!(otherObject instanceof Employee)) return false
            if(getClass() != otherObject.getClass()) return false;
            // 5
            Employee other = (Employee) otherObject;
            // 6
            return name.equals(other.name)
                    && salary.equals(((Employee) otherObject).salary)
                    && hireDay.equals(((Employee) otherObject).hireDay);
        }
    }
    

    Classを使用するかinstanceofを使用するかを比較するには、2つの異なる状況からこの問題を見ることができます.
  • サブクラスが独自の等しい概念を持つことができる場合、対称性要件はgetClassを強制的に使用してチェックされます.
  • スーパークラスによって等しい概念が決定されると、instanceofを用いて検出することができ、異なるサブクラスのオブジェクト間で等しい比較を行うことができる.

  • 次に、hashCodeメソッドを記述するための推奨事項を示します.
    a、ゼロ以外の定数値をresultというintタイプの変数に保存します.
    b、オブジェクト内の各キードメイン(値equalsメソッドで考慮される各ドメイン)について、いくつかのステップを完了する.
    1.当該ドメインのintタイプのハッシュコードcを計算する:
    1.1、ドメインがbooleanタイプの場合、計算(f?0:1).
    1.2.ドメインがbyte、char、shortまたはintタイプである場合、(int)fが計算される.
    1.3.ドメインがfloatタイプの場合、Float.floatToIntBits(f)が計算される.
    1.4.ドメインがlongタイプである場合、計算(int)(f^(f>>32)).
    1.5.ドメインがdoubleタイプである場合、Double.doubleToLongBits(f)を計算してlongタイプの値を求め、ステップ4に従ってそのlongタイプの値にハッシュ値を計算する.
    1.6.ドメインがオブジェクト参照であり、クラスのequalsメソッドがequalsを再帰的に呼び出すことによってこのドメインを比較する場合、同様にこのドメインに対してhashCodeを再帰的に呼び出す.より複雑な比較が必要な場合は、このドメインの「仕様表示」を計算し、このパターン表示に対してhashCodeを呼び出します.このドメインの値がnullの場合、0(または他の定数)が返されます.
    1.7.ドメインが配列である場合、各要素は別々のドメインとして処理される.すなわち、上記のルールを再帰的に適用し、重要な要素ごとにハッシュコードを計算し、以下の方法に従ってこれらのハッシュ値を組み合わせる.
    2、次の式に従って、ステップ1で算出したハッシュコードc resultに結合:result=31*result+c.
    c、resultを返します.
    d、「等しいインスタンスが等しいハッシュコードを有するか否か」を検証する.
    hashCodeメソッドはorg.apache.commons.lang.builder.HashCodeBuilderというツールクラスで簡単に書き換えることができます.