小编典典
对于泛型类型,主要要了解的是它们不是协变的。
因此,尽管您可以这样做:
final String string = "string";
final Object object = string;
以下内容将无法编译:
final List strings = ...
final List objects = strings;
这是为了避免您绕过通用类型的情况:
final List strings = ...
final List objects = strings;
objects.add(1);
final String string = strings.get(0);
因此,一一讲解您的示例
1个
您的通用方法采用a
List,而您采用List>;(基本上是)List。T可以分配给Object类型,并且编译器满意。
2
您的通用方法相同,您传入List>。T可以分配给List>类型,编译器再次感到高兴。
3
这与 2 基本上相同,但具有另一层嵌套。T仍然是List>类型。
4
这是有点梨形的地方,也是我从上面提出的观点。
您的通用方法采用List>。您通过了List>。现在,由于通用类型不是协变的,List>因此无法将其分配给List。
实际的编译器错误(Java 8)是:
必填:java.util.List> 找到:
java.util.List> 原因:无法推断类型变量T
(参数不匹配;java.util.List>无法转换为java.util.List>)
基本上,编译器告诉您,T由于必须推断List外部列表中嵌套的类型,因此找不到分配的对象。
让我们更详细地看一下:
List>是List的 一些未知类型 -它可以是一个List或一个List;
我们可以get这样做Object, 但是我们不能add。因为否则我们会遇到我提到的协方差问题。
List>是List的List一些未知类型的-
它可能是一个List>或一个List>。在情况 1中
,可以分配T给通配符列表,Object但不允许add对通配符列表进行操作。在第 4种 情况下,此操作无法完成-
主要是因为没有通用的构造可以防止add外部攻击List。
如果在第二种情况下将编译器分配T给Object,则可能会出现如下所示的情况:
final List> list = ...
final List> wildcard = list;
wildcard.add(Arrays.asList("oops"));
因此,由于协方差,不可能安全地将a分配List>给 任何其他 泛型List。
2020-09-18