27
Effective Java輪読会 vol.0 2章 項目1,2 充根

Effective Java輪読会 vol0

Embed Size (px)

Citation preview

Effective Java輪読会 vol.0第2章 項目1,2

李 充根

今日の流れ

• 19:30-19:45 自己紹介

• 19:45-19:55 勉強会説明

• 19:55-20:20 輪読会の進め方検討

• 20:30-21:15 輪読発表・議論

• 21:15-21:30 次回日程・発表者検討

• 第0回なので今後の進め方を一緒に考えましょう

2014/4/4 EffectiveJava輪読会 2

自己紹介

• 名前・HN

• 仕事・研究

• 趣味

• 好きなエディタ

• 好きなemacs lisp

• Etc…

2014/4/4 EffectiveJava輪読会 3

自己紹介

• 名前:李充根(リ・チュングン)

• HN:りぐん

• twitter:@choonggeun @ligunligun

• FB:choonggeun

• 言語:C/C++、C#、Java

• 趣味:プリキュア実況、アイカツ

• 西プロ主催

2014/4/4 EffectiveJava輪読会 4

勉強会説明

• そもそものきっかけ– twitter

– https://twitter.com/choonggeun/status/444791870179123200

• 本買ったのはいいけどボリューム多いし一人で勉強するのだるい!• Effective Javaは訳が良くなくて固いことで有名• みんなで勉強すれば負担は減るかな• まぁそんな感じです

• 対象・前提知識– Java7くらいまでの基礎– GoFデザインパターン

• 参考– http://www.techscore.com/

2014/4/4 EffectiveJava輪読会 5

進め方

• 一回につき2人位発表?

• 一回につき一章くらいのペースかな

(11章あるので月一で大体一年くらい)

• (発表(20分)+議論(20分))*2かな?

• 全発表後、次回の発表者を決める

• その他何か意見があれば

2014/4/4 EffectiveJava輪読会 6

発表

• 第2章 オブジェクトの生成と消滅

– 項目1 staticファクトリーメソッド

– 項目2 ビルダーパターン

2014/4/4 EffectiveJava輪読会 7

コンストラクタの代わりにstaticファクトリーメソッドを検討する

項目1

2014/4/4 EffectiveJava輪読会 8

項目1 staticファクトリーメソッド

• 通常のインスタンス生成

• Staticファクトリーメソッド(not GoFのファクトリーメソッ

ド)

2014/4/4 EffectiveJava輪読会 9

Class Hoge{public Hoge(){

//何か処理}

}

public static Boolean valueOf(boolean b){return b ? Boolean.TRUE : Boolean.False

}

メリット1 名前を持つ

• コンストラクタのパラメータだけではオブジェクトを表せない時でも適切な名称を与えることができる

• 例(確率的素数を返す)

2014/4/4 EffectiveJava輪読会 10

BigInteger(int, int, random)

BigInteger.probablePrime(int, random) ※Java 1.4で追加

Hoge(String, int)Hoge(int, String)

メリット2 新しいオブジェクト生成が必要ない

• 予め用意しておいたインスタンスを使用、すでに生成したインスタンスをキャッシュすることによりインスタンス生成を低減

• インスタンス生成のコストが高い時に有効

• GoFのFlyweightパターンに類似

• 例– Boolean.valueOf(boolean b)

– シングルトンのgetInstance()

• インスタンス制御されている

• シングルトン(項目3)、インスタンス化不可能(項目4)

2014/4/4 EffectiveJava輪読会 11

メリット3 戻り値を任意のサブタイプで返すことができる

• 返すオブジェクトをpublicにすることなくインスタンスを生成できる

• インターフェイスに基づくフレームワーク(項目18)に向く

• 概念的重みが軽くなる

• 例

– EnumSet

– RegularEnumSet, JumboEnumSet

2014/4/4 EffectiveJava輪読会 12

メリット4 インスタンス生成の面倒さの低減

• 通常だと

• staticファクトリーメソッドを用いて

というメソッドが定義されていると

と簡略化できる

2014/4/4 EffectiveJava輪読会 13

Map<String, List<String>> m = new HashMap<String, List<String>>();

※Java6以前

pubic static <K, V> HashMap<K, V> newInstance(){return HashMap<K, V>();

}

Map<String, List<String>> m = HashMap.newInstance();

※Java7以降ではダイアモンド演算子で次のように書ける

Map<String, List<String>> m = new HashMap<>();

デメリット1 サブクラスを作れない

• 問題点

– privateコンストラクタのみのクラスではサブクラスを作れない

• 例

– コレクションフレームワークの各実装?

• 解決策

– 継承ではなくコンポジションの使用(項目16)

2014/4/4 EffectiveJava輪読会 14

デメリット2 他のstaticメソッドと区別がつかない

• 問題点– コンストラクタのように目立たない– staticファクトリーメソッドかどうか知ることが困難

• 解決策– 命名規則に従う

• 例– valueOf

– of

– getInstance

– newInstance

– getType

– newType

2014/4/4 EffectiveJava輪読会 15

数多くのコンストラクタパラメータに直面した時にはビルダーを検討

項目2

2014/4/4 EffectiveJava輪読会 16

項目2 ビルダーパターン

• テレスコーピングコンストラクタ

2014/4/4 EffectiveJava輪読会 17

public class 栄養成分{private final int 分量; //必須private final int 総容量; //必須private final int カロリー; //オプションprivate final int 脂肪; //オプションprivate final int 炭水化物; //オプションprivate final int タンパク質; //オプション

public 栄養成分(int 分量, int 総容量, int カロリー, int 脂肪,int 炭水化物, int タンパク質){this.分量 = 分量;this.総容量 = 総容量;this.カロリー = カロリー;this.脂肪 = 脂肪;this.炭水化物 = 炭水化物;this.タンパク質 = タンパク質;

}}

テレスコーピングコンストラクタ

• 次のように各オプションを定義

2014/4/4 EffectiveJava輪読会 18

public 栄養成分(int 分量, int 総容量){this(分量, 総容量, 0, 0, 0, 0);

}public 栄養成分(int 分量, int 総容量, カロリー){

this(分量, 総容量, カロリー, 0, 0, 0);}public 栄養成分(int 分量, int 総容量, カロリー, 脂肪){

this(分量, 総容量, カロリー, 脂肪, 0, 0);}public 栄養成分(int 分量, int 総容量, カロリー, 脂肪, 炭水化物){

this(分量, 総容量, カロリー, 脂肪, 炭水化物, 0);}

テレスコーピングコンストラクタ

• 使い方

• 問題点

– 書きにくい

– 読みにくい

– 多数のパラメータの時煩雑になる

– パラメータの順番などバグの温床となる

2014/4/4 EffectiveJava輪読会 19

栄養成分 コーラ = new 栄養成分(240, 8, 100, 0, 35, 27);

JavaBeansパターン

• 不整合を許す

2014/4/4 EffectiveJava輪読会 20

public class 栄養成分{private int 分量 = -1; //必須private int 総容量 = -1; //必須private int カロリー = 0; //オプションprivate int 脂肪 = 0; //オプションprivate int 炭水化物 = 0; //オプションprivate int タンパク質 = 0; //オプション

public 栄養成分(){ }

public void set分量(int val){ this.分量 = val; }public void set総容量(int val){ this.総容量 = val; }public void setカロリー(int val){ this.カロリー = val; }public void set脂肪(int val){ this.脂肪 = val; }public void set炭水化物(int val){ this.炭水化物 = val; }public void setタンパク質(int val){ this.タンパク質 = val; }

}

※JavaBeans

再利用性の向上のため1. 引数なしコンストラクタ2. setter/getter

が定義された単純なクラス

JavaBeansパターン

• 使い方

• 問題点

– 不整合な状態になる

– クラスを不変にする可能性を排除(項目15)

– スレッドセーフにするために労力がかかる

2014/4/4 EffectiveJava輪読会 21

栄養成分 コーラ = new 栄養成分();コーラ.set分量(240);コーラ.set総容量(8);コーラ.setカロリー(100);コーラ.炭水化物(35);コーラ.タンパク質(27);

ビルダーパターン

• 栄養成分クラス

2014/4/4 EffectiveJava輪読会 22

public class 栄養成分{private final int 分量; //必須private final int 総容量; //必須private final int カロリー; //オプションprivate final int 脂肪; //オプションprivate final int 炭水化物; //オプションprivate final int タンパク質; //オプション

public static class Builder{……

}

private 栄養成分(Builder builder){分量 = builder.分量;総容量 = builder.総容量;カロリー = builder.カロリー;脂肪 = builder.脂肪;炭水化物 = builder.炭水化物;タンパク質 = builder.タンパク質;

}}

ビルダーパターン

• ビルダークラスの詳細

2014/4/4 EffectiveJava輪読会 23

public static class Builder{private final int 分量;private final int 総容量;

private int カロリー = 0;private int 脂肪 = 0;private int 炭水化物 = 0;private int タンパク質 = 0;

public Builder(int 分量, int 総容量){this.分量 = 分量;this.総容量 = 総容量;

}

//続く→

ビルダーパターン

• ビルダークラスの詳細

2014/4/4 EffectiveJava輪読会 24

//←続き

public Builder カロリー(int val){ カロリー = val; return this; }public Builder 脂肪(int val){ 脂肪 = val; return this; }public Builder 炭水化物(int val){ 炭水化物 = val; return this; }public Builder タンパク質(int val){ タンパク質 = val; return this; }

public 栄養成分 build(Builder builder){分量 = builder.分量;総容量 = builder.総容量;カロリー = builder.カロリー;脂肪 = builder.脂肪;炭水化物 = builder.炭水化物;タンパク質 = builder.タンパク質;

}}

ビルダーパターン

• 使い方

• 利点– 読みやすい

– 書きやすい

• 欠点– テレスコーピングコンストラクタより冗長

– パフォーマンスに影響がある(場合がある)

2014/4/4 EffectiveJava輪読会 25

栄養成分 コーラ = new 栄養成分.Builder(240, 8).カロリー(100).炭水化物(35).タンパク質(27).build();

まとめ

• 同一のパラメータ数で別々のオブジェクトを生成したり、コンストラクタだけでは適切な名称ではないときstaticファクトリーメソッドを検討する

• 可変の多数のパラメータで初期化したい時ビルダーパターンをしようする

2014/4/4 EffectiveJava輪読会 26

次回日程・発表者

• 希望日時

• 発表者選出

• 項目分け

2014/4/4 EffectiveJava輪読会 27