为什么在实例化过程中不能在顶层使用通配符,而在实例化过程中却可以在所有其他级别使用通配符?

时间:2019-09-16 14:50:30

标签: java generics types wildcard instantiation

例如,如果我有以下课程:

class MyObject<T> {}

为什么会这样:

class Main {
    public static void main(String[] args) {        
        MyObject<MyObject<?>> moMo = new MyObject<MyObject<?>>();
    }
}

但不是这样:

class Main {
    public static void main(String[] args) {
        MyObject<?> mo = new MyObject<?>();
    }
}

我不明白为什么其中一种可能,而另一种则不可能。我开始相信,许多小差异不是故意设计的,而是语言中的古怪之处。


我知道这里也有类似的问题(thisthisthis);但是,没有人回答为什么为什么,而没有另一个。

1 个答案:

答案 0 :(得分:0)

考虑

    List<?> list1 = new ArrayList<>();
    List<?> list2 = new ArrayList<List<?>>();
    List<?> list3 = new ArrayList<?>(); // WRONG

    list2.add(new ArrayList<Integer>()); // WRONG

在第三种错误的情况下,创建了一个实际的列表,其通用参数类未绑定到左侧已声明的参数类(也是?) 。 通配符类型可能无法直接实例化。

您可能会new ArrayList<Integer>()(或new ArrayList())告诉您允许的类型。这些存储在Class.getType parameters()中。因此,new ArrayList<?>()无法存储在该ArrayList实例的对象实际类中。对于通用类,运行时类擦除不占100%。

在第二种情况下,这种立即实例化不会发生。

add表明了通配符类型的这种用法很繁琐/不切实际, 实际的list2可能是List<List<String>>

对于那些使用其他语言的更强大的文字系统的人来说:更好 避免尝试使用过于巧妙的类型表达式。