2017-06-30 10 views
2

これらの2種類の汎用関数の間に暗黙の違いはありますか、コンパイラはそれらを同じものとして扱いますか?これらの2つの汎用関数の相違点

public static void test(List<? extends Number> list) { 
    for (Number t : list) { 

    } 
} 

public static <T extends Number> void test(List<T> list) { 
    for (T t : list) { 

    } 
} 

また、他の上の1つを使用してのいずれかの利点がありますか。

+0

最初のものは[汎用メソッド](https://docs.oracle.com/javase/tutorial/extra/generics/methods.html)ですが、後者はそうではありません。 – QBrute

+0

機能的に同一です。 2番目の利点は、冗長型変数を持たないことです。私は、型変数の数の違いのため、コンパイラによって異なる扱いを受けていると思います。 –

+0

また、よく読んでください:[一般的な方法を使用するタイミングとワイルドカードを使用するタイミングは?](https://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use – azurefrog

答えて

3

これらは機能的に同一です。だから、もう一つは短い方として好ましいする必要があります。

public static void test(List<? extends Number> list) { 
    for (Number t : list) { 

    } 
} 

あなたが宣言された型に頼る何かを返したいとき最初のものは、より理にかなっています。

たとえば、このコードは、戻り値の型に関してより柔軟である:

public static <T extends Number> List<T> test(List<T> list) { 
    for (T t : list) { 

    } 
    return list; 
} 

あなたはこの方法でそれを呼び出すことができます。

List<Integer> integers = ...; 
integers = test(integers); 

ため、戻り値の型で使用される宣言パラメーター化された型で、コンパイラは、メソッドの結果を代入する変数の型から戻り値の型を推論します(もちろん型制約と互換性がなければなりません)。

しかしList<Integer>は、あなたもこの方法を使用することができますList<? extends Number>のサブタイプであるとして:リストの戻り値の型でパラメータ化された型を宣言しなくて

List<Integer> integers = ...; 
List<? extends Number> numbers = test(integers); 

を、あなただけにメソッドの結果を割り当てることができますList<? extends Number>で宣言された型:

public static List<? extends Number> test(List<? extends Number> list) { 
    for (Number t : list) { 

    } 
    return list; 
} 

だから、唯一この方法が有効である:

List<Integer> integers = ...; 
List<? extends Number> numbers = test(integers); 
関連する問題