/**
* GenericContractでは、hashCode()メソッドのオーバーライドを行っていないので、
* 「等しいオブジェクトは、同じハッシュコードを持たなければならない。」という
* 制約に違反してしまうので、このサンプルで、hashCode()をオーバーライドする。
* もし、このままであると、HashMap, HashSet, Hashtableを含むハッシュ系のコレクションで
* 適切な動作が出来なくなる。
*/
package com.util;
/**
* 論理的等価性(logical equality)が必要で、且つスーパークラスがそれに対応する
* equals()メソッドを実装していない場合に、equals()メソッドを実装する。
* また、equals()メソッドを実装する際には、一般契約(Generic Contract)を守らなければ
* ならない。この契約違反をした場合、JVM実装はどのような振る舞いをするか分からない。
* 一般契約一覧
*
* - 反射性(Reflexivity)
* - 対称性(Symmetry)
* - 推移性(Transitivity)
* - 整合性(Consistency)
* - 非null性(Non-nullity)
*
*
* - equalsをオーバーライドする時は、常にhashCodeをオーバーライドしなければならない
*
* @see 実装参考 Effective Java 第3章項目7 equalsをオーバーライドする時は一般契約に従う
*
* @author s-okita
*/
public class GenericContract2 {
private int status;
public GenericContract2() {
status = 0;
}
public GenericContract2(int status) {
this.status = status;
}
/**
* reflexive contract
* Symmetric contract
*/
public boolean equals(Object obj) {
// 下記、Exceptionを生成しないように実装する事が、equals一般契約である。
// NullPointerException.
// ClassCastException
// 最初に行うのはnullチェックではなく、instanceof
// これにより、NullPointerException, ClassCastExceptionを回避する。
//if (obj != null) {
if (obj instanceof GenericContract2) {
// for debug
if (this == obj) { // reflexive
return true;
} else {
// Symmetric
if (this.status == ((GenericContract2)obj).getStatus()) {
return true;
}
}
}
return false;
}
public int hashCode() {
// ここでHash関数を利用すべきではない。
// Hash関数に依存するため、またHash関数などは数学的要素が
// 多数を占めるのでパフォーマンスの影響を受けかねない。
//return new Random().nextInt();
//return 1;
int result = 17; // 17,37 are a prime number.
result = 37 * result + status;
return result;
}
/**
* @return
*/
public int getStatus() {
return status;
}
/**
* @param i
*/
public void setStatus(int i) {
status = i;
}
}