18

以下のコードを実行すると、出力は 2 になります。これは、セットに 2 つの要素が含まれていることを意味します。ただし、両方のオブジェクトがhashcode()値とメソッドに基づいて等しいため、セットには 1 が含まれている必要があると思います.equals()。私の理解の明らかな間違いのようですか?

package HELLO;

import java.util.HashSet;
import java.util.Set;

public class Test {

    public static void main(String[] args) throws Exception {
        Set<Alpha> s = new HashSet<Alpha>();
        Alpha a1 = new Alpha();
        Alpha a2 = new Alpha();
        s.add(a1);
        s.add(a2);
        System.out.println(s.size());
    }
}   

class Alpha {
    int a = 10;

    public int hashcode() {
        return a;
    }

    public boolean equals(Object obj) {
        return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
    }

    public String toString() {
        return "Alpha : " + a;
    }
}
4

3 に答える 3

34

ハッシュコード メソッドは Object クラスのハッシュ コード メソッドをオーバーライドしないため、 equalsメソッドは hashCode の結果と一致しないため契約を破り、「等しい」が異なる hashCode を持つオブジェクトを持つことができます

覚えておいてください:@Overrideメソッドをオーバーライドするときは、常にアノテーションを使用する必要があります。これは、このエラーや同様のエラーをキャッチするのに役立ちます。

@Override  // ** don't forget this annotation
public int hashCode() { // *** note capitalization of the "C"
  return a;
}

また、特にレビューのためにここにコードを投稿する場合は、コードのフォーマットを改善する必要があります。コードが標準に準拠している場合は、コードをよりよく理解し、サポートすることができます (標準が存在するのはそのためです)。したがって、同じレベルでインデントされた同じブロック内にあるすべてのコード行とインデントの一貫性を保つようにしてください。インポート、外部クラスの宣言、およびその最後の中括弧を含む基本レベルのコードが左にフラッシュされていることを確認する必要があります。 :

import java.util.HashSet;
import java.util.Set;

public class Test {

   public static void main(String[] args) throws Exception {
      Set<Alpha> s = new HashSet<Alpha>();
      Alpha a1 = new Alpha();
      Alpha a2 = new Alpha();
      s.add(a1);
      s.add(a2);
      System.out.println(s.size());
   }
}

class Alpha {
   int a = 10;

   @Override
   public int hashCode() {
      return a;
   }

   public String toString() {
      return "Alpha : " + a;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      Alpha other = (Alpha) obj;
      if (a != other.a)
         return false;
      return true;
   }
}

これに関する美しいレビューについては、以下をお読みください: Java での equals と hashCode のオーバーライド

于 2013-05-09T13:12:05.323 に答える
4

@Overrides アノテーションは、スーパークラスで同名のメソッドをオーバーライドするためのものです。」

@Override
public int hashCode() {
    return a;
}

@Override
public boolean equals(Object obj) {
    return (obj instanceof Alpha && ((Alpha) obj).a == this.a);

}

@Override
public String toString() {
    return "Alpha : " + a;
}
于 2013-05-09T13:14:10.887 に答える
4

メソッドのハッシュコードには、 hashCode (大文字の「C」)という名前を付ける必要があります。

メソッドをオーバーライドする予定がある場合は、@Overrideアノテーションを使用する必要があります。

If you had used that annotation, you'd have noticed the problem earlier as the code wouldn't have compiled.

于 2013-05-09T13:14:54.427 に答える