Read OnlyなIterable (List)

型宣言は汎用的にすべきか?

というか,Read onlyなIterableをあらかじめ用意しとけって感じもしますね.ラッパをいちいち自分で書くのは面倒すぎ.

ラッパはCollectionフレームワークに用意されていて、

List<Hoge> list = new ArrayList<Hoge>();
list = Collections.unmodifiableList(list);

で変更不能なListが取得できる。このリストに対してaddやremoveを呼ぶとUnsupportedOperationExceptionがスローされる。

型宣言は汎用的にすべきかという話題に触れると、上記のようにList型へのadd、removeはUnsupportedOperationExceptionの可能性が常に付きまとう。Listの実装がLinkedListであったりするとadd以外のオペレーションは遅い。このように実装クラスによって操作の特性に違いがあり、実装不明の抽象型に対する操作は結果が不明であるため好ましくない。変更操作は具象型で宣言した変数に対して行うべきである。

処理がメソッド内で閉じている、つまり実装がArrayListと分かり切っていればList型変数に入れても同じように思える。しかし、閉じているならば多態性の恩恵がなく、抽象型を使う理由もない。

型によってプログラマの意図を伝えることができる。

List list = new ArrayList();

このようにList型で宣言したならば特に実装はこだわらないという意思表示。あとでnewしている実装クラスをLinkedListに変更しても問題ない、場合によっては積極的に変更すべき、と捉える事が出来る。

ArrayList list = new ArrayList();

こうすれば、ここはArrayListの特性を利用したいので、他の実装ではダメだというプログラマの意思表示になる。

というわけで何も考えずList型変数を使う、というのはよろしくない。

Collections

java.util.Collectionsのメソッドでは、Listを同期化するsynchronizedListが有名だが、reverseやmin、shuffleなどの操作や、NullObjectパターンのためのemptyListなど微妙に便利なメソッドが揃っている。

Javaでは思いつく大抵の機能は既存である。足りなければApache Commonsを探すといい。仕事でWebアプリ等を作っているならできる限り既存クラスを使った方が良いだろう。