なぜArrayListの参照変数はList型で宣言しなければならないのか
Advertisements
掲題の疑問について考えてみよう。
ついでに一度リストについてまとめる。
package sample2; import java.util.ArrayList; import java.util.List; public class ListSample { public static void main(String[] args){ //① ArrayList<String> list = new ArrayList<String>(); List<Integer> list2 = new ArrayList<Integer>(); //②コンパイルエラー //List<int> list3 = new ArrayList<int>(); for(int i = 0; i < 10; i++){ list2.add(i); } //list2:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] System.out.println("list2:"+list2); //size():10 サイズ System.out.println("size():"+list2.size()); //get():3 要素取得 System.out.println("get():"+list2.get(3)); //contains():true 含まれているか System.out.println("contains():"+list2.contains(5)); } }
②コレクションの要素は参照型しか指定できない。基本型だとコンパイルエラーになる
①について
ArrayList<String> list = new ArrayList<String> List<String> list = new ArrayList<String>
この2つの参照変数の宣言の違いは何か。
それは、Listがインタフェース型でArrayListが具象クラスである。
一般的に下の
List
が望ましいとされる。
理由は、インターフェースは変更されにくいものだからだ。
具象クラスは実装を持つため変化しやすい。
ソースコードは変更の影響を受けにくいものが望ましい。
もっとわかりやすい例で見てみよう。
package sample2; public interface Oya { void sayHello(); void sayGoodBye(); }
このインターフェースを継承する子クラス
package sample2; public class Ko implements Oya{ private Ko(){} @Override public void sayHello() { // TODO 自動生成されたメソッド・スタブ System.out.println("Hello!"); } @Override public void sayGoodBye() { // TODO 自動生成されたメソッド・スタブ System.out.println("GoodBye!"); } //ファクトリメソッド風に static Ko getInstance(){ Ko ko = new Ko(); return ko; } }
さて、以下のコードを実行した結果はどうなるだろうか?
package sample2; public class Main2 { public static void main(String[] args){ //インターフェース型として宣言している。 Oya ko = Ko.getInstance(); ko.sayHello(); ko.sayGoodBye(); } }
結果
Hello! GoodBye!
インターフェース型として宣言すれば、具象クラスの振る舞いを利用しつつも、
変更に影響を受けにくいコードを書くことができるのである。