11

1 は機能し、2 は機能しないのはなぜですか?

1:

public List<? extends Integer> l1;
public List<? extends Number> l2 = l1;

2:

public List<U> l1;
public List<S> l2 = l1;
//where U and S have been previously defined as: **S extends Number,U extends Integer**
4

4 に答える 4

3

ジェネリックは共変ではありません。例えば:

List<Integer> l1;
List<Number> l2;
l1 = l2; // incompatible types
l2 = l1; // also incompatible

ただし、ワイルドカード型は共分散を表現する方法を提供します。

List<? extends Integer> l1;
List<? extends Number> l2 = l1; //legal

l1は、 または extendsListある不明な型のとして表現されていIntegerます。同様に、l2isListまたは extends の型ですNumberIntegerextends以来Number、コンパイラはへの代入が問題ないことを知っていl1ますl2

この状況は異なります。

<S extends Number, U extends Integer> void someMethod() {

    List<U> l1;
    List<S> l2 = l1; //incompatible types
}

Sおよびは型パラメーターです。つまり、 (または型推論)Uの呼び出し元によっていくつかの特定の型引数が提供されます。これらの型引数は、ワイルドカード キャプチャのsomeMethodような具象型にすることができます。Integer

それらも境界付きですが、これは上記のような境界付きワイルドカードの使用とは異なります。型パラメーターは宣言時に制限されます。メソッド本体内では、変更されないと理解されています。たとえば、 と の両方Sが次の呼び出しによってU解決されたとします。Integer

this.<Integer, Integer>someMethod();

この場合、メソッド本体は次のようになると想像できます。

List<Integer> l1;
List<Integer> l2 = l1; // okay why not?

これは合法ですが、たまたま運が良かっただけです。そうではない状況もたくさんあります。例えば:

this.<Double, Integer>someMethod();

ここで、メソッド本体を再考します。

List<Integer> l1;
List<Double> l2 = l1; // danger!

したがって、境界付きの型パラメーターは、境界付きのワイルドカードとは大きく異なるものであることがわかります。これにより、さまざまなジェネリック型を共変的に「スワップイン」できます。

List<Integer> l1;
List<Double> l2;
List<? extends Number> l3;
l3 = l1;
l3 = l2;
于 2013-04-03T14:50:45.333 に答える
1

Integerところで:は拡張できません。クラスですIntegerfinal

// l1 holds any subclass of Integer and, because Integer implements Number it is also a subclass of Number
public List<? extends Integer> l1;
// l1 (see above) implements Number so this is fine.
public List<? extends Number> l2 = l1;

// Using Integer here instead of your U because you cannot extend Integer - it is final.
public List<Integer> l3;
// Make S extend Number
static class S extends Number {
  // Implementing the abstract methods of Number
}
// NOT valid because l4 must be a List of S not a list of ANY Number and l3 is a List<Integer> - no connection other than a commmon interface.
public List<S> l4 = l3;
于 2013-04-03T10:21:59.807 に答える
-1

1.1 では Integer を拡張する任意のクラスを、1.2 では Number を拡張する任意のクラスを意味します。Integer は Number のサブクラスであるため、最初のケースではエラーが発生しませんでした。しかし、2.1 は U だけを言っていて、2.2 では S だけを言っています。

 public List<S> l2 = l1

l1 は S ではなく U 型であり、ジェネリックはそれ自身によるそのようなオブジェクト参照をサポートしていません。最初のケースで使用したように、ワイルド カードを使用する必要があります。

 public List<? extends Number> l2 = l1;

あなたの問題を解決します..

于 2013-04-03T10:17:22.217 に答える
-2

1では、整数と数値のサブクラスをそれぞれ言っているからです。

しかし、2 番目に、U と S のジェネリックと言っていますが、このジェネリックは、Java OOP のサブクラス オブジェクトの概念を参照できるスーパーをサポートしていません。

于 2013-04-03T10:07:21.990 に答える