2008-08-24 6 views
19

私はJava関数を定義している:それを呼び出すためにタイプ引数を汎用Javaメソッドに明示的に渡すことができないのはなぜですか?

static <T> List<T> createEmptyList() { 
    return new ArrayList<T>(); 
} 

一つの方法は、それほどのようなものです:

List<Integer> myList = createEmptyList(); // Compiles 

は、なぜ私は明示的にジェネリック型引数を渡すことで、それを呼び出すことはできませんか? :

Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why? 

コンパイラからエラーIllegal start of expressionが返されます。

+1

Cheekysoftは理由を説明するが、あなたは本当に必要性が単に静的な関数呼び出しの前にクラス名を追加し、第二のタイプのDEFを追加感じる場合: 一覧ます。myList = MyClassの。 createEmptyList(); –

答えて

28

Javaコンパイラが静的メソッドに対してパラメータ型を推論できない場合は、常に完全修飾メソッド名:Classを使用して渡すことができます。 <タイプ>メソッド();

Object list = Collections.<String> emptyList(); 
+6

非staticメソッドの場合、 ' Object list = this。thisキーワードを使用することができます。 emptyList(); ' – Roland

1

あなたがそれを行うことはできませんなぜ

私は、Javaの部分に掘ったので、かなりの時間でしたが、...は、おそらく言語の開発者が設計上の選択でした。それでも、Javaによって採用されたtype erasureのため、ジェネリック情報はコンパイル時に破棄されるため、あなたの例では、型パラメータを持っているかどうかにかかわらず、まったく同じバイトコードが作成されます。

22

メソッドパラメータとして型を渡すことができます。

static <T> List<T> createEmptyList(Class<T> type) { 
    return new ArrayList<T>(); 
} 

@Test 
public void createStringList() { 
    List<String> stringList = createEmptyList(String.class); 
} 

方法は、タイプができるのと同様なので、動的型付けの一般的な戻り値の型を持つメソッドのための唯一のオプションでgenericisedすることはできません - それは一口:-)だあー - で渡すことです引数としての型

Java genericsに関する本当に優れたFAQはsee Angelika Langer's generics FAQです。


フォローアップ:

それは、Collection.toArray(T[])のように配列引数を使用するには、この文脈では意味がありません。配列が使用されている唯一の理由は、結果が格納される配列が配列全体に収まる大きさであれば、同じ配列が事前に割り当てられているためです。これにより、実行時に常に新しい配列を割り当てる必要がなくなります。あなたは、配列の入力を使用したいなかった場合

はしかし、教育の目的のために、構文は非常に似ています

static <T> List<T> createEmptyList(T[] array) { 
    return new ArrayList<T>(); 
} 

@Test 
public void testThing() { 
    List<Integer> integerList = createEmptyList(new Integer[ 1 ]); 
} 
+1

-1これは、他の引数がコンパイラにジェネリック型を推論させない場合に、クラスリテラルを汎用メソッドに渡す必要があるという誤解です。本当に必要なのは、[Xavier's answer](http://stackoverflow.com/a/25877)に記載されている構文だけです。とにかく、[Henrikの答え](http://stackoverflow.com/a/24996)に言及すると、変数にすぐに代入されたときに、新しいジェネリックオブジェクトの型パラメータを指定するための実際の使用例はありません。コンパイル時であっても、その変数はそれ以降重要です。これがJava 7の '<>'構文の背後にある理由です。 –

+0

あなたは 'type'パラメータを使用しないので、それを渡すべきではありません – newacct

0

@pauldoo はい、あなたは全く正しいです。これは、Javaジェネリックimhoの弱点の1つです。

私はCheekysoftに反応しました。T [] AbstractCollection#toArray(T [] a)のように、Javaの人々自身がどのようにして行うのかを見たいと提案したいと思います。私はCheekysoftsのバージョンが優れていると思うが、Javaのものは親しみやすいという利点がある。

編集:リンクを追加しました。 再編集:CheekysoftのSO :)


フォローアップにバグを発見: まあ、それは対応する例を返却しなければならないいくつかのタイプのリストは以下のようになるはずであるよう:

static <T> List<T> createEmptyList(List<T> a) { 
    return new ArrayList<T>(); 
} 

しかし、はい、クラスオブジェクトを渡す方が明らかに優れています。私の唯一の議論は親密さの議論であり、この正確な例ではそれほど価値はない(実際には悪い)。

関連する問題