为什么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**
答案 0 :(得分:3)
Generics are not covariant。例如:
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
表示为{{1>} 某种未知类型,即List
。同样,Integer
是l2
某种类型的List
,是Number
。由于Integer
扩展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;
答案 1 :(得分:1)
顺便说一句:你无法延伸Integer
,Integer
是final
类。
// 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;
答案 2 :(得分:-1)
Look In 1.1你说的是任何扩展Integer的类,1.2中任何扩展Number的类。现在是这样一种方式Integer是Number的子类,这就是为什么它在第一种情况下没有给出任何错误。但是2.1是你只说U而2.2只做S而你正在做
public List<S> l2 = l1
和l1的类型为U而不是S,并且泛型不支持此类对象引用。您将不得不使用第一种情况下使用的外卡。
public List<? extends Number> l2 = l1;
将解决您的问题..
答案 3 :(得分:-2)
因为在1中你分别说整数和数字的任何子类。
但是在第二个你说U和S的Generic并且喜欢这个泛型不支持Super可以引用java OOP的Sub类对象概念。