Collectionの活用 その1 Listの宣言は「List<E> list = new ArrayList<E>();」?

最近Javaの開発でListを多用しているのでCollectionインターフェースについて
整理しておこうと思います。

今回はListの宣言の仕方についてです。


私がプログラマー1年目の時に先輩に指摘されたのですが、
Stringのリストを宣言するときに、基本的には
List<String> list = new ArrayList<String>();
と書きます。

ArrayList<String> list = new ArrayList<String>();
ではダメなのでしょうか。

 

結論を言うと、基本的には

List<String> list = new ArrayList<String>();

で宣言しておくのが良いが、100点ではありません。


そもそも
①List<String> list = new ArrayList<String>();
と宣言するのと
ArrayList<String> list = new ArrayList<String>();
で宣言するのでは何が違うのでしょうか。


Listはインターフェースなので、Listを実装するArrayListクラスではListインターフェースが持つ抽象メソッドを全て実装しています。
addやgetなど、Listの基本的な機能の実装はArrayListクラスに書かれています。
実はArrayListクラスにはListが持つ抽象メソッド以外にも、独自の機能を持っています。
trimToSizeやensureCapacityなどがそれにあたるのですが、ArrayList独自の
使い道のよくわからない機能が実装されています。

これらArrayList独自の機能は①で宣言した場合は使用できず、②で宣言した場合に使用することができます。
言い換えると、trimToSizeやensureCapacityといったメソッドを使いたい場合、②で宣言しなければならいということです。

上記を踏まえると、①で宣言するよりも②で宣言したほうが多くの機能が使えるので
はじめのうちは②で宣言すればいいのではと思いがちです。


ArrayListクラスの機能を使うことが確定しているなら↑の考え方で問題ありません。
しかし、オブジェクト指向のインターフェースの考え方から、仕様と実装は分離するべきであり、オブジェクト指向言語であるJavaで書くなら型はListにするのが好ましいです。

なぜかというと、
もし開発の途中段階で、ArrayListをそのまま使うと不便な個所があり、Listインターフェースを実装した独自のクラスを作成(ここではOriginalArrayListとする)し、そちらを使いたいとなった場合、

①で宣言していた場合、修正はArrayList⇒OriginalArrayListのリファクタリングだけで
済む(Listの機能しか実装していないため)のですが、
②で宣言してしまっていた場合、ArrayListの独自メソッドを使用していた部分の実装は手で修正する必要がでてきます。


Listの例では上記のような修正が入ることはほとんどないですが、
実際の開発ではコーディングの途中、またはコーディング完了後にやっぱり実装を変更しようなんてことがしょっちゅうあります。その際修正範囲をできるだけ限定するためのインターフェースなのかなと思います。

インターフェースを使うメリットと実装側の機能をしっかり理解した上で変数宣言しましょう。

 


ブログの記事を書くのは初めてですが、ずいぶん長い文章になってしまいました…。
読みにくくすみません。
このブログを通してもっと情報をスマートに伝えられるスキルを身に着けるのが課題ですね。
精進します。