Effective Java第40章-@overrideプレゼンテーションを一貫して使用
ユーザ自身が定義したクラスをデータ型とするSetデータ構造を用いる場合,equals,hashcodeなどを正しく再定義して重複をチェックする必要がある.(Override)
このセクションでは、equalsを再定義するときに「再定義」ではなく「マルチ定義」を行うことが主なエラーです.
まず,以下のコードはaからzまでのforループを10回実行し,Set資料構造に追加する.
Setは反復を許さないためequalsを再定義し,漏れはなく,以下の性質を守るためhashCodeも再定義した.の2つのオブジェクトがequalsによって同じと判定された場合、hashCodeも同じであるべきである. しかし、このドメインは成立せず、2つのオブジェクトがequalsによって異なると判定されてもhashCodeは同じである可能性がある. 主にSet,HashMapなどの資料構造では,HashCodeを用いてパケットを決定し,equals比較値を用いて挿入したい要素が既に存在するかどうかを調べる.
上記の性質に従えば、以下のコードは26を出力すべきである.しかし、次のコードは実際に260の結果を出力する.
上図はSetクラスでequalsとhashCodeを宣言する部分です.
正しく修正されたコードは以下の通りです.
@Overrideをペーストしても、パラメータを変更しないとコンパイルできません.
@Overrideは追加されていませんが、コードの整合性と再定義の事実を明確に残しておくとよいでしょう.
コアの整理
すべての再定義メソッドに@Overrideコメントを意識して追加すると、コンパイラはエラーが発生したときにすぐに通知します.例外は一つしかありません.特定のクラスで親の抽象メソッドを再定義した場合は、このコメントを追加する必要はありません(有害ではありません).
このセクションでは、equalsを再定義するときに「再定義」ではなく「マルチ定義」を行うことが主なエラーです.
まず,以下のコードはaからzまでのforループを10回実行し,Set資料構造に追加する.
Setは反復を許さないためequalsを再定義し,漏れはなく,以下の性質を守るためhashCodeも再定義した.
上記の性質に従えば、以下のコードは26を出力すべきである.しかし、次のコードは実際に260の結果を出力する.
package com.example.Bigram;
import java.util.HashSet;
import java.util.Set;
public class Bigram {
private final char first;
private final char second;
public Bigram(char first, char second) {
this.first = first;
this.second = second;
}
public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
public int hashCode() {
return 31 * first + second;
}
public static void main(String[] args) {
Set<Bigram> s = new HashSet<>();
for (int i = 0; i < 10; i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
s.add(new Bigram(ch, ch));
}
}
System.out.println("크기는 26으로 예상됩니다. 실제 크기 : " + s.size());
}
}
これはequalsメソッドのパラメータが親クラスでObjectであるためである.上図はSetクラスでequalsとhashCodeを宣言する部分です.
正しく修正されたコードは以下の通りです.
package com.example.Bigram;
import java.util.HashSet;
import java.util.Set;
public class Bigram {
private final char first;
private final char second;
public Bigram(char first, char second) {
this.first = first;
this.second = second;
}
public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Bigram))
return false;
Bigram b = (Bigram) o;
return b.first == first && b.second == second;
}
public int hashCode() {
return 31 * first + second;
}
public static void main(String[] args) {
Set<Bigram> s = new HashSet<>();
for (int i = 0; i < 10; i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
s.add(new Bigram(ch, ch));
}
}
System.out.println("크기는 26으로 예상됩니다. 실제 크기 : " + s.size());
}
}
@Overrideコメントを貼り付け、パラメータをObjectに変更します.@Overrideをペーストしても、パラメータを変更しないとコンパイルできません.
@Overrideは追加されていませんが、コードの整合性と再定義の事実を明確に残しておくとよいでしょう.
コアの整理
すべての再定義メソッドに@Overrideコメントを意識して追加すると、コンパイラはエラーが発生したときにすぐに通知します.例外は一つしかありません.特定のクラスで親の抽象メソッドを再定義した場合は、このコメントを追加する必要はありません(有害ではありません).
Reference
この問題について(Effective Java第40章-@overrideプレゼンテーションを一貫して使用), 我々は、より多くの情報をここで見つけました https://velog.io/@gkak1121/Effective-Java-41장-Override-애너테이션을-일관되게-사용하라テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol