2010-02-25
Effective Java 読書会 8 日目 「それ enum で出来るよ」
はじめに
今日読んだところ
143 ページ〜 159 ページ
前回はこちら
Effective Java 読書会 7 日目 「PECS! PECS! PECS!」 - IT戦記
int 定数とか使わない
型安全じゃないから
enum 使う
enum Hoge {
FOO, BAR;
}
簡単
メソッドも持てる
enum Hoge { FOO, BAR; void a() { /* (snip) */ } }
で、以下のように使う
Hoge.FOO.a();
シングルトンも
switch 文の代わりに固有メソッド
enum Hoge { FOO { void a() { /*snip*/ } }, BAR { void a() { /*snip*/ } }; abstract void a(); }
以下のコードが
// これはダメ switch(obj) { case Hoge.FOO: /*snip*/ break; case Hoge.BAR: /*snip*/ break; default: throw new AssertionError(); }
以下で良くなる!
// case の書き忘れもなくて安心!
obj.a();
戦略 enum
enum の値をカテゴライズする
// たとえば enum Hoge { FOO { void a() { /*snip*/ } }, // これと BAR { void a() { /*snip*/ } }, // これがまったく同じ処理だったとして BAZ { void a() { /*snip*/ } }; abstract void a(); }
以下のようになる
enum Hoge { FOO(Strategy.STRATEGY_1), BAR(Strategy.STRATEGY_1), BAZ(Strategy.STRATEGY_2); private enum Strategy { STRATEGY_1 { void a() { /* ... */ } }, STRATEGY_2 { void a() /* ... */ } abstract void a(); } // 戦略の委譲 private final Strategy strategy; Hoge(Strategy strategy) { this.strategy = strategy; } void a() { strategy.a(); } }
values 便利
for (Hoge v : Hoge.values()) { /* ... */ }
ordinary は使うのはやめましょう
値が増えるとコンパイルの度に順番変わるので
private で id 的なフィールドを持てと
EnumSet 便利!
64 個までならビット演算(|)と比べても遜色のない速度で動く!テラすごす!!
Set<Hoge> set = EnumSet.of(Hoge.FOO, Hoge.BAR, Hoge.BAZ); // ビット演算 FOO (=0x1) | BAR (=0x1 << 1) | BAZ (=0x1 << 2) と比べても遜色のない速度で動く
of メソッドかっけー!
EnumMap も便利
Enum の ordinal をインデックスにした配列じゃなく EnumMap を使おう
まとめ
enum すげー便利!めっちゃ使う!
次回はこちら
Effective Java 読書会 7 日目 「PECS! PECS! PECS!」
はじめに
今日読んだところ
126 ページ〜 142 ページ
前回はこちら
Effective Java 読書会 6 日目 「ジェネリクス!」 - IT戦記
Object を使ったその瞬間が
ジェネリック型を使うチャンスなのです!!!
たとえば、以下みたいな
public class Stack { /* snip */ public Object pop() { /* snip */ } public void push(Object e) { /* snip */ } }
こうなる
public class Stack<E> { /* snip */ public E pop() { /* snip */ } public void push(E e) { /* snip */ } }
Object を使わなくすると
キャストがなくなる
キャスト良くない!例外でるからね!
どうしてもキャストしなきゃだめなパターン
配列をラップするためのジェネリックス型を使う場合は、キャストしなきゃしょうがない
public class Stack<E> { private E[] elements; Stack() { elements = new E[100]; // 出来ません>< } public E pop() { /* snip */ } public void push(E e) { /* snip */ } }
なので、
public class Stack<E> { private E[] elements; Stack() { elements = (E[]) new Object[100]; // とか } public E pop() { /* snip */ } public void push(E e) { /* snip */ } }
public class Stack<E> { private Object[] elements; Stack() { elements = new Object[100]; } public E pop() { element = (E) elements[index]; // みたいな /* snip */ } public void push(E e) { /* snip */ } }
論理的に安全なことを確認して、 @SuppressWarnig("uncheck") しちゃいな YO!
ジェネリックメソッドもアルよねー
アルよねー
コンストラクタの型推論するために static なジェネリックメソッドつかうよねー
よねー
コンストラクタの型推論
Java 7 では HashMap<String, String> map = new HashMap<>(); みたいになるらしい YO! という話がでた
PECS! PECS!
プロデューサは extends 、コンシューマは super だってばよ!
たとえば、
public Hoge { // producer は CharSequence のプロデューサ // consumer は CharSequence のコンシューマ public static void foo(List<? extends CharSequence> producer, List<? super CharSequence> consumer) { // プロデューサからは get できる CharSequence hoge = producer.get(0); // コンシューマには set できる consumer.set(0, hoge); // 以下はコンパイルエラー producer.set(0, hoge); hoge = consumer.get(0); } }
ジェネリックな型を作ったら
境界ワイルドカードを意識せずにその型を使えるか確認する
super extends も問題なく使えるか確認。
型トークン
Class> を渡すことを型トークンというよ!静的動的に型安全!
まとめ
魔法の弾丸 PECS!


