java - 嵌套的ArrayList初始化有问题吗?

标签 java generics collections bounded-wildcard

考虑以下这些类:

class A{ }
class B extends A{ }

据我们所知,这可以很好地编译:

List<? extends A> xx = new ArrayList<B>();
List<? extends List<? extends A>> xy = new ArrayList<List<? extends A>>();

但这会导致编译时错误

List<? extends A> yx = new ArrayList<? extends A>();
List<? extends List<? extends A>> yy = new ArrayList<? extends List<? extends A>>();

错误说:

required: class or interface without bounds

我知道编译器为上述初始化解释的新值是不同的,因此不能安全地转换它们。 但是上面错误信息中的'without bounds'是什么意思呢?

最佳答案

此错误是指创建新的 ArrayList,其直接顶级类型参数使用通配符。这是不允许的,尽管 嵌套 类型参数允许具有通配符。

JLS, Section 15.9, "Class Instance Creation Expressions" , 状态:

If TypeArguments is present immediately after new, or immediately before (, then it is a compile-time error if any of the type arguments are wildcards (§4.5.1).

这里的关键词是“立即”,因为它代表直接类型参数,而不是嵌套类型参数。

这是Angelika Langer's article about generics and its usages中提到的限制:

They [wildcards] can not be used for creation of objects or arrays, that is, a wildcard instantiation is not permitted in a new expression. Wildcard instantiations are not types, they are placeholders for a member from a family of types. In a way, a wildcard instantiation is similar to an interface: we can declare variables of interface types, but we cannot create objects of interface types; the created objects must be of a class type that implements the interface. Similar with wildcard instantiations: we can declare variables of a wildcard instantiated type, but we cannot create objects of such a type; the created objects must be of a concrete instantiation from the family of instantiations designated by the wildcard instantiation.

(强调我的)

基本上,通配符类型不是具体类型,不能被实例化,与不允许直接创建接口(interface)实例类似。

然而,这并没有说明嵌套通配符,它​​与最初不相关的对象的创建有关,这些对象最终可能与该类型相关联。在您的示例中,这将是可以添加到外部 ArrayList 的嵌套 List。它们可以是对任何匹配通配符类型的 List 的引用,但它们并未在此处创建。

总结

Java 不允许在实例创建表达式中使用通配符(使用 new),但它允许在此类表达式中使用嵌套通配符,因为直接通配符类型不是具体类型。

关于java - 嵌套的ArrayList初始化有问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49390530/

相关文章:

Scala 从泛型实例化一个具体类

java - 在java中为抽象类创建方法

c# - Collection.Contains() 使用什么来检查现有对象?

java - Spring - 注入(inject) vavr 集合

java - 如何隐藏VSCode的Java编译器路径?

java - Maven:包 org.junit 不存在,即使它在 pom.xml 的依赖项列表中声明

java - 如何在 javafx 中获取 label.getWidth()

java - Java 1.5 之前的集合框架实现是通用的吗?

java - Map 和 Hashtable 的 ConcurrentModification 异常

java - 为什么我在尝试运行 JavaFx 应用程序时出现 java.lang.ClassNotFoundException?