type引数を一般的なJavaメソッドに明示的に渡せないのはなぜですか?
質問
Java関数を定義しました:
static <T> List<T> createEmptyList() {
return new ArrayList<T>();
}
それを呼び出す1つの方法は次のとおりです。
List<Integer> myList = createEmptyList(); // Compiles
ジェネリック型の引数を明示的に渡して呼び出すことができないのはなぜですか? :
Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why?
コンパイラからエラーIllegal start of expression
を受け取ります。
解決
Javaコンパイラが静的メソッドのパラメータタイプを単独で推測できない場合、完全修飾メソッド名Classを使用していつでも渡すことができます。 <!> lt;タイプ<!> gt; method();
Object list = Collections.<String> emptyList();
他のヒント
メソッドパラメータとして型を渡すと、できます。
static <T> List<T> createEmptyList( Class<T> type ) {
return new ArrayList<T>();
}
@Test
public void createStringList() {
List<String> stringList = createEmptyList( String.class );
}
メソッドは型と同じ方法でジェネリック化することはできないため、動的に型指定されたジェネリック戻り型を持つメソッドの唯一のオプション、つまり一口のphewは、型として渡すことです引数。
Javaジェネリックに関する非常に優れたFAQについては、アンジェリカランガーのジェネリック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 ] );
}
Javaのこれらの部分を掘り出してからかなり時間が経ちましたが、...
それができない理由は、おそらく言語開発者による設計上の選択でした。それでも、Javaで採用されているタイプ消去のため、とにかくコンパイル時にジェネリック情報が削除されるため、この例では、typeパラメーターがあるかどうかにかかわらず、まったく同じバイトコードが作成されます。
@pauldoo はい、あなたはまったく正しいです。これは、Javaジェネリックimhoの弱点の1つです。
Cheekysoftへの回答T [] AbstractCollection#toArray (T [] a)。 Cheekysoftsバージョンは優れていると思いますが、Javaバージョンには親しみやすさがあります。
編集:リンクを追加しました。 再編集:SOにバグが見つかりました:)
Cheekysoftのフォローアップ: 返されるべきタイプのリストであるため、対応する例は次のようになります。
static <T> List<T> createEmptyList( List<T> a ) {
return new ArrayList<T>();
}
しかし、はい、クラスオブジェクトを渡す方が明らかに優れています。私の唯一の議論は親しみやすさの議論であり、この正確な例ではあまり価値がありません(実際には悪いことです)。