11
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

スッキリわかるJAVA 実践編

良い本との呼び声高かったので、Java復習を兼ねて読んだ。


スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

確かに良い本だと思います。これまでなんとなく知ってた事なども一通り整理できた。章立てとか、話の順番も素晴らしく整理されていて、最後までさくさく読める。

以下、理解があやふやだった点を中心に覚書。(一部だけだが・・・)


toString() / equals() / hashCode()のオーバーライドについて

第1部 第4章
classを作成した時は、これらのメソッドをオーバーライドしないと、コレクションが正しく動作しない場合がある。
例えば

ArrayList#remove()

内部でequals()を呼んで等価判定を行っているため、正しく動かなくなる。ただし、等価判定されることが明らかに不要なクラスではオーバーライドの必要はない(データではないクラス)

HashSet, HashMap, HashTable

equals()メソッドはコストが高いため、常に実施するわけではない。hashCode()を使って効率的に比較している。だからオーバーライドは必須です。

  • toString() 文字出力しとく。
  • equals() 等価であることを保証する。開発者が正しいと考える等価判定アルゴリズムをJVMに伝えることが目的
  • hashCode() 等価であるインスタンスからは必ず同じハッシュ値を返す。異なるインスタンスからはなるべく異なるようにする。
public class Employee {
    private String name;
    private int age;
    private String address;
...
    public String toString() {
        return "名前:" + this.name + "年齢:" + this.age
              + "住所" + this.address;
    }

    public boolean equals(Object o) {
        if (o == this) return true;
        if (o == null) retrun false;
        if (!(o instanceof Employee)) return false;

        Employee r = (Employee) o;
        if (!this.name.trim().equals(r.name.trim())) return false;
        if (!this.age.equals(r.age)) return false;
        if (!this.address.trim().equals(r.address.trim())) return false;

        return true;
    }

    public int hashCode() {
        int result = 11;    // 0以外の適当な値
        result = result * 31 + name.hashCode(); // 奇数かつ素数
        result = result * 31 + age;
        result = result * 31 + address.hashCode();
        return result;
    }
}

このあたりはEffective Javaでも数ページ割いて説明されています。

reflectionについて

第1部 第7章

リフレクションを使うと、アクセス制御(private/protected/...)を無視してメンバを利用することができる。

シリアライズ

第2部 第10章

例えばインスタンスをそのままファイルに保存するときにシリアライズする。

public class Employee implements Serializable {
    ....
}

public class Main {
    public  static void main(String[] args) throws Exception {
        Employee employee1 = new Employee();

        // Save
        FileOutputStream fos = new FileOutputStrem("c:¥¥data.dat");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(employee1);
        oos.flush();
        oos.close();

        // Restore
        FileInputStream fis = new FileInputStream("c:¥¥data.dat");
        ObjectInputStream ois = new ObjectInputStream(fish);
        Employee employee2 = (Employee)ois.readObject();
        ois.close();
    }

}

注意点
* Serializableを実装してないフィールドは直列化されない。そのフィールドは復元時nullになる。
* Staticのフィールドは対象にならない
* transientで修飾したフィールドは対象にならない

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
11
Help us understand the problem. What are the problem?