Java通配符与类型参数

时间:2013-04-03 10:01:50

标签: java generics

为什么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 个答案:

答案 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。同样,Integerl2某种类型的List,是Number。由于Integer扩展Number,编译器知道将l1分配给l2必须没问题。

这种情况不同:

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

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

SU是类型参数,这意味着someMethod(或类型推理)的调用者会为它们提供一些特定类型的参数。这些类型参数可以是具体类型,如Integer或通配符捕获。

虽然它们也是有界的,但这与使用上面的有界通配符不同。类型参数以声明为界限 - 在方法体内,它们被理解为不会改变。例如,假设SU已通过调用解析为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)

顺便说一句:你无法延伸IntegerIntegerfinal类。

// 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类对象概念。