考虑以下这些类:
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/