为了账号安全,请及时绑定邮箱和手机立即绑定

泛型方法上的多个通配符使Java编译器(还有我!)很迷茫

泛型方法上的多个通配符使Java编译器(还有我!)很迷茫

浮云间 2019-07-25 14:14:58
泛型方法上的多个通配符使Java编译器(还有我!)很迷茫让我们首先考虑一个简单的场景(见ideone.com上的完整源代码):import java.util.*;public class TwoListsOfUnknowns {     static void doNothing(List<?> list1, List<?> list2) { }     public static void main(String[] args) {         List<String> list1 = null;         List<Integer> list2 = null;         doNothing(list1, list2); // compiles fine!     }}这两个通配符是不相关的,这就是为什么您可以调用doNothing带着List<String>和一个List<Integer>..换句话说,这两个?可以引用完全不同的类型。因此,以下内容不编译,这是预期的(也在ideone.com上):import java.util.*;public class TwoListsOfUnknowns2 {     static void doSomethingIllegal(List<?> list1, List<?> list2) {         list1.addAll(list2); // DOES NOT COMPILE!!!             // The method addAll(Collection<? extends capture#1-of ?>)             // in the type List<capture#1-of ?> is not applicable for             // the arguments (List<capture#2-of ?>)     }}到目前为止还不错,但事情开始变得很混乱。如ideone.com所见):import java.util.*;public class LOLUnknowns1 {     static void probablyIllegal(List<List<?>> lol, List<?> list) {         lol.add(list); // this compiles!! how come???     }}上面的代码是在Eclipse中为我编译的sun-jdk-1.6.0.17在ideone.com中,但是它应该吗?难道我们不可能List<List<Integer>> lol和一个List<String> list,类似的两个不相关的通配符情况TwoListsOfUnknowns?实际上,以下对这个方向的轻微修改并不是编译的,这是预期的(如ideone.com所见):import java.util.*;public class LOLUnknowns2 {     static void rightfullyIllegal(             List<List<? extends Number>> lol, List<?> list) {         lol.add(list); // DOES NOT COMPILE! As expected!!!             // The method add(List<? extends Number>) in the type             // List<List<? extends Number>> is not applicable for             // the arguments (List<capture#1-of ?>)     }}所以看起来编译器正在做它的工作,但是我们得到了这个(如ideone.com所见):import java.util.*;public class LOLUnknowns3 {     static void probablyIllegalAgain(             List<List<? extends Number>> lol, List<? extends Number> list) {         lol.add(list); // compiles fine!!! how come???     }}再一次,我们可能有List<List<Integer>> lol和一个List<Float> list所以这不应该编译,对吧
查看完整描述

3 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞


不是专家,但我想我能理解。

让我们将您的示例更改为类似的内容,但使用更有区别的类型:

static void probablyIllegal(List<Class<?>> x, Class<?> y) {
    x.add(y); // this compiles!! how come???}

让我们把清单改为[],以便更有启发性:

static void probablyIllegal(Class<?>[] x, Class<?> y) {
    x.add(y); // this compiles!! how come???}

现在,x是一列一些班级类型。它是一个数组任何班级类型。它可以包含一个Class<String>  a Class<Int>..这不能用普通类型参数表示:

static<T> void probablyIllegal(Class<T>[] x  //homogeneous! not the same!

Class<?>是一种超级类型的Class<T>任何 T..如果我们认为类型一组对象 Class<?>是所有人的联合Class<T>为所有人T..(它包括它自己吗?我不知道.)




查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 425 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信