コンテンツアシストでよく出てきて、メソッド名からたぶんこう使うんだろうな~くらいに思っていたメソッドにいろいろ意味やオーバーライドの必要があると知ったので覚書。
一覧
メソッド | 操作内容 | 関連するクラス |
---|---|---|
toString() | 文字列表現を得る | Object |
equals() | 等価判定を行う | Object |
hashCode() | ハッシュ値を得る | Object |
compareTo() | 大小関係を判定する | Comparable |
clone() | 複製する | Object、Cloneable |
toString()
呼び出してみたら「Test@4124c5a」とかなって、デバッグに使えねーな!とかなるやつ。
意味不明な文字はObjectクラスのメソッドが呼び出されているので、おとなしくオーバーライドする。
equals()
オブジェクトが等価かどうか比較する。 何をもって等価とするかはクラス作成者次第なので定義してやる必要がある。 オーバーライドしないと思わぬバグにぶち当たることになる(ArrayListのremoveメソッドとか)
例
public boolean equals(Object o){ if(o == this) return true; if(o == null) return false; if(!(o instanceof XXXClass)) return false; XXXClass r = (XXXClass) o; if(!this.xxField.equals(r.xxField)) return false; return true; }
hashCode()
各フィールド値に対して影響を与えるなどしてインスタンスのハッシュ値を得る。 equals()と同じく、オーバーライドしないと思わぬバグにぶち当たることになる(HashSetのremoveとか)
例
public int hashCode(){ int result = 37; result = result * 31 xxxField.hashCode(); result = result * 31 +yyyField; return result; }
compareTo()
きちんと宣言しておけば以下のような呼び出しでソートできるようになる。
List<XXXClass> list = new ArrayList<XXXClass>();
Collections.sort(list);
compareToの実装ルールは以下の通り
条件 | 戻り値 |
---|---|
自分自身のほうが比較対象よりも小さい場合 | 負の数 |
自分自身と比較対象が等しい場合 | 0 |
自分自身のほうが比較対象よりも大きい場合 | 正の数 |
実装例
public class XXXClass implements comparable<XXXClass> { int number; public int compareTo(XXXClass obj){ if(this.number < obj.number){ return -1; if(this.number > obj.number){ return 1; } return 0; } }
clone()
インスタンスを複製したいときに。
インタフェースを実装する必要がある。
実装例
public class XXXClass implements Cloneable { String name; YYYClass y; public XXXClass clone(){ // public でオーバーライドする XXXClass result = new XXXClass(); result.name = this.name; result.y = this.y.clone(); return result; } }
補足メモ
removeメソッドでバグがでる理由は、内部的にeqalusやhashCodeを呼び出しているから。
HashSetではコストの大きいequalsをいきなり呼び出すことはせず、低コストのhashCodeで同じっぽいかどうかをまず判定している