2015-01-08 5 views
5

無制限または上限のあるジェネリックにワイルドカードを使用する目的は何ですか?具体的には:Javaジェネリックス - 下限を除くワイルドカードの目的ですか?

public static <E> void foo(List<E> bar)の代わりにpublic static void foo(List<?> bar)と言うのはなぜですか?

public static <E extends Baz> void foo(List<E> bar)の代わりにpublic static void foo(List<? extends Baz> bar)と言うのはなぜですか?

+0

簡潔性は、おそらく? – aroth

答えて

2

ワイルドカードを持つバージョンが好まれています。それ以外の場合は、List<Number>印刷します。パラメータのタイプがList<?>の場合、Listのいずれかが受け入れられることが明らかです。 Listが受け入れられた場合は、型パラメータに名前を付ける理由はないので、<E>と書くのは面倒です。一方、型パラメータが署名内に2回現れた場合、ワイルドカードは使用できません。たとえば、このシグネチャには型パラメータが必要です。引数が(ワイルドカードなしで3種類のパラメータ、総混乱を持っているだろうことを行うための唯一の方法)タイプList<? extends E>を持っていた場合

public static <E> List<E> combineLists(List<E> list1, List<E> list2) 

は実際にその一例では、それはおそらく良いだろう。

有効なJavaでは、メソッド本体にtypeパラメータが必要な場合でも、ワイルドカードを使用して署名のバージョンを優先し、これを可能にするプライベートヘルパーメソッドを記述することをお勧めします。たとえば、

public static void swapFirstAndLast(List<?> list) { 
    helper(list); 
} 

private static <E> void helper(List<E> list) { 
    int size = list.size(); 
    E e = list.get(0); 
    list.set(0, list.get(size - 1)); // These lines would not be possible 
    list.set(size - 1, e);   // If the type of list were List<?> 
} 
+0

実際のタイプパラメータを除くすべての場所でワイルドカードを配置できます。つまり、これは有効な構文ですが、 'public static リスト combineLists(List list1、List list2)'は、実装しようとして嫌いです。 – Makoto

4

次のコードでEを参照することがない場合は、それを宣言する必要はありません。

プログラマメモリの負担を軽減します。

+1

うん、まさに私が言うつもりだった。ジェネリック型は、実際には構文的な砂糖ではなく、何かをすることを可能にするためのものです。 – asteri

2

リストのタイプが実行時に決定される場合は、ワイルドカードを使用する必要があります。

次のプログラムは、コマンドライン引数を指定して実行するとList<String>を出力します。

public class Test { 

    public static List<String> listOfStrings = Arrays.asList("hello", "world"); 
    public static List<Number> listOfNumbers = Arrays.asList(1, 2, 3, 4.5); 

    public static List<?> getListOfUnknown(boolean arg) { 
     if(arg) return listOfStrings; 
     else return listOfNumbers; 
    } 

    public static void main(String[] args) { 
     System.out.println(getListOfUnknown(args.length > 0)); 
    } 
} 
+0

OPの推論の行を使って、あなたは 'public List getListOfUnknown(boolean arg)'のようなことを行います。私はそれを推薦しているわけではありません。 – asteri

+0

@asteriしかし、 'T'をコンパイル時に知る必要があるので、' getListOfUnknown'または ' getListOfUnknown'を呼び出す必要があります。 – immibis

+0

ああ、あなたが言っていることが分かります。申し訳ありませんが、メソッドの本体ではなくメソッドのシグネチャを読み込んだだけです。私の間違い。 – asteri

関連する問題