Effective Java(項目22〜24)

金曜分を更新するのを忘れていました。不調だった昨日の分と併せて。前回分もタイトルを書いていなかったので修正。

○項目22 関数ポインタをクラスとインタフェースで置き換える

  • Cの関数ポインタをクラスとインタフェースで置き換えるには、戦略(Strategy)パターンを実装する。

→Strategyパターンに関するひどいメモはこちら http://d.hatena.ne.jp/shaw27/20060124/1138109192

○項目23 パラメータの正当性を検査する

  • ほとんどのメソッドとコンストラクタは、パラメータとして渡される値に関して何らかの制約を持っている。

→このような制約は明確に文書化すべきであり、メソッド本体の初めに検査を行うことで制約を強制する必要がある。

  • publicのメソッドについては、パラメータに関する制約が守られていない場合にスローされる例外をJavadocの@throwsタグに記述

→IllegalArgumentException, IndexOutOfBoundsException, NullPointerException など

  • パラメータに対する任意の制約が良いことである、というわけではない

→メソッドは出来るだけ一般的に(制約を意識しなくて済む程度に)設計されるべき


○項目24 必要な場合には、防御的にコピーする

  • クラスのクライアントは、クラスの不変式を破壊する為に徹底した努力をすると想定する

→それは言いすぎだとしても、単純な間違いによる予期しない振舞いへの対策として防御的なプログラムが必要

  • 防御的コピーの例(コンストラクタの場合)
private final Date start;
private final Date end;

//これを
public Period(Date start, Date end) {
  if (start.compareTo(end) > 0)
    throw new EllegalArgumentException();
  this.start = start;
  this.end   = end;
}

↓

//こうする
public Period(Date start, Date end) {
  //防御的コピー
  this.start = new Date(start.getTime());
  this.end   = new Date(end.getTime());
  
  //検査もあとから行う
  if (start.compareTo(end) > 0)
  throw new EllegalArgumentException();

}
  • 防御的コピーにはcloneメソッドを用いても良い場合と良くない場合がある
    • コピー対象がサブクラス化できる型の場合はcloneメソッドがオーバーライドされている可能性も有り良くない
    • 例えばDate型のようにjava.util.Dateであることが明確な場合はcloneメソッドでも良い(但し必須というわけでもない)