凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 47518
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

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
コメント
  • # re: Javaの型推論Utilsクラスのカラクリ
    かつのり
    Posted @ 2008/04/15 19:32
    java.util.Arrays#asList(T...)のことも、たまには思い出してあげてください。。。

  • # re: Javaの型推論Utilsクラスのカラクリ
    katzchang
    Posted @ 2008/04/16 2:15
    >型推論の仕掛けは非常にうまいと思うのですが、ListといえばArrayListという考え方がいただけない。

    インスタンス生成時、↓のようにクラスを渡すようにすると何とかなったりします。Listでも応用可能だと思います。

    public static <K,V> Map<K, V> newMap(Class<? extends Map> mapClass){
    try {
    return mapClass.newInstance();
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }

    http://d.hatena.ne.jp/katzchang/20080130/1201672269
  • # re: Javaの型推論Utilsクラスのカラクリ
    凪瀬
    Posted @ 2008/04/16 9:05
    Classを渡して動的にnewする方法ですか。
    確かにコレならデフォルトコンストラクタの存在するMapならなんでも生成できますね。

    Collections.unmodifiableMap()とかもnewMap()の外で噛ませばいいのか。
  • # re: Javaの型推論Utilsクラスのカラクリ
    凪瀬
    Posted @ 2008/04/16 11:22
    Java言語仕様じゃなくてプログラミング言語Javaを見ていたことに今気がついた orz
    本文中の書名は修正しておきました。
    言語仕様側のどの章が当たるのかは今夜にでも記載します。
  • # re: Javaの型推論Utilsクラスのカラクリ
    通りすがり
    Posted @ 2008/04/16 15:54
    >Hoge hoge = new Hoge();
    >hoge.<String>hoge();

    この構文は知らなかった・・・。知らない人大勢いそう。
  • # re: Javaの型推論Utilsクラスのカラクリ
    凪瀬
    Posted @ 2008/04/17 1:28
    ジェネリックメソッドは知る人ぞ知る構文のひとつですね…。

    言語仕様側の該当の章を記載しておきました。
    8.4.4 ジェネリックメソッド
    15.12.2.7 実引数に基づく型引数の推論
    を読めばこの挙動についての情報を得ることができます。
    英語版の言語仕様はWebから参照できます。
    http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html

    書籍では日本語訳が出ています。
    http://www.amazon.co.jp/dp/4894717158
  • # re: Javaの型推論Utilsクラスのカラクリ
    calico
    Posted @ 2008/07/17 10:03
    はじめまして。

    > しかし、冒頭引用した
    > ArrayList<String> strs = list();
    > はコンパイル時に型安全ではないという警告は発せられません。

    id:unageanuさんに別件で検証して頂いたのですが、警告が出ないのはEclipseのコンパイラ(ECJ)を使用した場合だけでJDKのコンパイラでは警告が出ます。
    > http://d.hatena.ne.jp/unageanu/20080715/1216115987

    皆さんNetBeans(JDK)も使いませう…orz
  • # cristi
    bogemi
    Posted @ 2011/09/27 22:36

    http://www.buysale.ro/anunturi/alba.html?localitate=puduri-bricesti - alba
  • # JurgenHiv USA MarionKer ShaniceHa Olympique De Marseille LoisCoole JermaineP West Ham United AveryQdkw Priscilla Tottenham Hotspurs Vernellvr Ermelinda Tyskland MarioCoup XiomaraCa Argentina LeonardoP OsvaldoMa Island SallyUxxf Eleanorvd Spanien Ka
    JurgenHiv USA MarionKer ShaniceHa Olympique De Ma
    Posted @ 2017/03/05 23:13
    JurgenHiv USA MarionKer
    ShaniceHa Olympique De Marseille LoisCoole
    JermaineP West Ham United AveryQdkw
    Priscilla Tottenham Hotspurs Vernellvr
    Ermelinda Tyskland MarioCoup
    XiomaraCa Argentina LeonardoP
    OsvaldoMa Island SallyUxxf
    Eleanorvd Spanien KayleneFa
    Maddisonx Olympique Lyonnais ZandraHol
    LetaAhren Leicester City Florencia
タイトル
名前
Url
コメント