Javaの型推論Utilsクラスというエントリで
Listなどのジェネリクスの型パラメータを省略する方法が書かれています。
// 型推論で空のインスタンス作成。
// 変数の型と値の型、同じ物を2回書かなくてOK。
ArrayList<String> strs = list();
HashMap<String, Date> dateMap = map();
HashSet<File> files = set();
気になるlist()の実装は
public static <T> ArrayList<T> list(T... items) {
return new ArrayList<T>(Arrays.asList(items));
}
といった感じ。
通常は代入時にジェネリクスの警告が出る
ジェネリクスの型パラメータを指定しない場合、代入の際に安全な代入ではないと警告されます。例えば
List<String> list = new ArrayList();
といったようにArrayList側のジェネリクスの型パラメータを省略するとコンパイル時に警告が出るわけです。
しかし、冒頭引用した
ArrayList<String> strs = list();
はコンパイル時に型安全ではないという警告は発せられません。
ジェネリックメソッド
タネはジェネリックメソッド("generic method" Java言語仕様3版 8.4.4 プログラミング言語Java4版 11.3参照)にあります。
ジェネリックメソッドというのは、特定のメソッドの呼び出し内だけで有効なジェネリクスの型パラメータ
(type parameter. 以下のコードでいうところの<T>のこと)を持つメソッドです。
以下のように記述します。
public <T> void hoge();
returnの型の手前にジェネリクス型パラメータのプレースホルダ(<T>)を記述します。
このメソッドの呼び出し側では
Hoge hoge = new Hoge();
hoge.<String>hoge();
といったようにメソッド名の手前にジェネリクス型パラメータを記述します。
このジェネリックメソッドのジェネリクス型パラメータはいくらかの推論が行われます。
プログラミング言語Javaの「11.6 正しいメソッドを見つける - 再訪」がわかりやすいでしょう。
2.メソッド呼び出しで、明示的な型引数がなくて、ジェネリックメソッドが適用可能であれば、
メソッド呼び出しで使用されている引数式の静的な型に基づいて、そのジェネリックメソッドの型引数が
推定されます。
型パラメータに対するすべての制約を満たす型を推定できなければ、そのメソッドは適用可能ではありません。
このように、ジェネリクス型パラメータは明示せずとも、引数の型や戻り値の型で
型パラメータが推定できる場合、コンパイル時警告とはなりません。
詳細にはJava言語仕様3版の「15.12.2.7 実引数に基づく型引数の推論」を参照してください。
たっぷり14ページに渡って推論のアルゴリズムについて記述されています。
例を挙げてみましょう。以下のように戻り値がT型の場合、
public <T> T hoge() {
次のように戻り型をStringと宣言すると推論してくれるわけです。
String str = hoge.hoge();
可変長引数で空の配列を作る
該当ソースでうまい点というのは、可変長引数を用いている点でしょう。
public static <T> ArrayList<T> list(T... items) {
return new ArrayList<T>(Arrays.asList(items));
}
通常、T型の配列をnewすることはできないのですが、可変長引数の場合はT型の配列を得られます。
このT型の配列をArrays#asList()に渡すことで、Listの生成と共に、初期値を与えることができるわけです。
このあたりの仕掛けは非常にうまいなと思いました。
でも、ArrayListってのはどうなの?
型推論の仕掛けは非常にうまいと思うのですが、ListといえばArrayListという考え方がいただけない。
UtilsクラスがArrayListを作るのはいいけども、
だったらそのメソッド名はlist()じゃいかんだろう、と思うわけです。
arrayList()とした方がよい。なぜなら他にもLinkedListを返すlinkedList()などを作ることができるから。
型パラメータを2回記述したくないことと、Listの実装クラスを選ばないことを混同してはいけませんよね。
とりあえずArrayListでいいやっていう人も多いと思いますが、データの特性を見て他のListの実装も使い分けましょう。
投稿日時 : 2008年4月15日 15:48