スッキリわかるJAVA 実践編


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



<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4844336770/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4844336770&linkCode=as2&tag=fkrw2960-22"><img border="0" src="http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4844336770&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fkrw2960-22" ></a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=fkrw2960-22&l=as2&o=9&a=4844336770" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4844336770/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4844336770&linkCode=as2&tag=fkrw2960-22">スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)</a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=fkrw2960-22&l=as2&o=9&a=4844336770" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />




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

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


***

# toString() / equals() / hashCode()のオーバーライドについて
*第１部 第４章*
classを作成した時は、これらのメソッドをオーバーライドしないと、コレクションが正しく動作しない場合がある。
例えば
#### ArrayList#remove()
内部でequals()を呼んで等価判定を行っているため、正しく動かなくなる。*ただし、等価判定されることが明らかに不要なクラスではオーバーライドの必要はない（データではないクラス）*

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

* toString()
 文字出力しとく。
* equals()
 等価であることを保証する。**開発者が正しいと考える等価判定アルゴリズムをJVMに伝える**ことが目的
* hashCode()
 等価であるインスタンスからは必ず同じハッシュ値を返す。異なるインスタンスからはなるべく異なるようにする。

```java
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でも数ページ割いて説明されています。
<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4621066056/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4621066056&linkCode=as2&tag=fkrw2960-22"><img border="0" src="http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4621066056&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fkrw2960-22" ></a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=fkrw2960-22&l=as2&o=9&a=4621066056" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />





# reflectionについて
*第１部 第７章*

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

# シリアライズ
*第２部 第１０章*

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

```java
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で修飾したフィールドは対象にならない