6

これはコレクションのコピー方法です(その一部):

public static <T> void copy(List<? super T> dst, List<? extends T> src) {
   for (int i = 0; i < src.size(); i++) {
     dst.set(i, src.get(i));
   }
}

4 つのサンプル コールがあります。

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);

1. Collections.copy(objs, ints);
2. Collections.<Object>copy(objs, ints);
3. Collections.<Number>copy(objs, ints);
4. Collections.<Integer>copy(objs, ints);

上記の呼び出しはどのように機能しますか?

いくつかの可能なシグネチャを使用してメソッドを宣言することもできます

1. public static <T> void copy(List<T> dst, List<T> src)
2. public static <T> void copy(List<T> dst, List<? extends T> src)
3. public static <T> void copy(List<? super T> dst, List<T> src)
4. public static <T> void copy(List<? super T> dst, List<? extends T> src)

上記の呼び出しの例では、

  • これらの最初のものは、宛先と送信元がまったく同じタイプの場合にのみ呼び出しを許可するため、制限が厳しすぎます。(了解) .

  • 2 番目の署名は、型パラメーターが Object の場合にのみ機能します

  • 3 番目のシグネチャは、型パラメーターが Integer の場合にのみ機能します

  • 最後のシグネチャは、Object、Number、および Integer の 3 つの型パラメーターすべてに対して機能します。

2 番目、3 番目、最後の署名についても説明してください。

残りの 3 つは、暗黙的な型パラメーターを使用する呼び出しと同等ですが、明示的な型パラメーターとは異なります。

この上記のステートメントはどういう意味ですか?

4

1 に答える 1

6

あなたの署名を一つ一つ考えてみましょう。

1. public static <T> void copy(List<T> dst, List<? extends T> src)

明示的な型パラメーターなしでこのメソッドを呼び出すと、最初の引数としてObject渡しているため、型パラメーターは として推論されます。List<Object>そして、List<? extends Object>を受け入れることができますInteger

ただし、明示的な型引数 を使用して呼び出す場合、 aをにNumber渡すことはできますが、ジェネリックは不変であるため、 andについては同じではありません。List<Integer>List<? extends Number>List<Object>List<Number>

2. public static <T> void copy(List<? super T> dst, List<T> src)

再び暗黙の型パラメーターの場合、に 2 番目の引数として渡すため、 としてT推論されます。And thenは の有効な代用です。IntegerList<Integer>List<T>List<Object>List<? super Integer>

明示的な型引数を指定してメソッドを呼び出す場合、第 1 引数としてNumber渡すことはできますが、第 2 引数としてList<Object>渡すことはできませんList<Integer>。上で説明したのと同じ理由で。

3. public static <T> void copy(List<? super T> dst, List<? extends T> src)

これで、このメソッド シグネチャはどの型でも機能します。推論される型パラメーターが何であれ、インスタンスdstのコンシューマーであるのTに対し、インスタンスsrcのプロデューサーですT。たとえば、明示的な型引数 を指定して呼び出した場合、NumberキャプチャList<Object>はに変換可能です。List<? super Number>同様に、List<Integer>キャプチャは に変換可能List<? extends Number>です。したがって、両方の引数は有効な置換です。

したがって、3 つのケースすべてで、型パラメーターを明示的に指定しなければ、コンパイラーは型パラメーターを正しく推論できます。ただし、ここでは 4 番目の署名を使用する必要があります。その理由は次のとおりです。

  • dstインスタンスの消費者であるTため、下限を使用する必要があります。
  • srcインスタンスのプロデューサーTので、上限を使用する必要があります。

関連記事:

参照:

于 2013-09-02T15:18:33.997 に答える