今日の自分を支える 技術→マネジメント

技術職→管理職になりました

Javaクラスの基本機能

コンテンツアシストでよく出てきて、メソッド名からたぶんこう使うんだろうな~くらいに思っていたメソッドにいろいろ意味やオーバーライドの必要があると知ったので覚書。

一覧

メソッド 操作内容 関連するクラス
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で同じっぽいかどうかをまず判定している