如何以类型安全的方式指定我希望在A
内允许任何实现List
接口的对象?我希望能够在所有对象上调用A的给定方法,关于它们是Class
类型。
public interface A (){}
List<? extends A> myList = new ArrayList<? extends A>();
我得到:Cannot instantiate the type ArrayList<? extends A>
如果我将通用版离开实例化方面它可以正常工作,但是我必须指定@SuppressWarnings({ "rawtypes", "unchecked" })
以使编译器对警告进行缄默。
答案 0 :(得分:3)
要了解为什么实例化new ArrayList<? extends A>()
没有意义,实际上我们可以用任意类或接口new ArrayList<B>()
等效地创建B
(即使不是与任何对象相关的,实现A
,并且可以将生成的创建的ArrayList安全地分配给类型为ArrayList<? extends A>
的变量。然后你可能想知道,哦,这是愚蠢的,因为我想要放入它的对象不属于B类,那么这又怎么样呢?但它 是相同的,因为无论如何你都不能把任何东西放入Something<? extends A>
类型的引用中。这就是创建new ArrayList<? extends A>()
。
如何指定我想要任何实现A的对象 以类型安全的方式允许在List内部使用的接口?一世 希望能够在所有对象上调用A的给定方法, 关于他们是什么类型。
这正是ArrayList<A>
的内容。它允许A
的所有实例(当然,实现A
的所有对象都是A
的实例),您可以在它们上使用A
的任何方法。这样的事情就是你想要的:
List<A> myList = new ArrayList<A>();
List<? extends A>
之类的东西仅用于从其他代码获取List对象的情况,而您不知道(或关心)他们创建的通用参数究竟是什么。 (在这种情况下,您无法将对象放入List中。)这与您的情况完全不同,其中您正在创建List对象,因此您决定并因此确切地知道使用了哪个泛型参数
答案 1 :(得分:2)
该问题与将类型参数绑定到接口无关,但是您无法使用通配符实例化参数化类型。 new ArrayList<? extends A>()
甚至new ArrayList<?>()
没有意义,因为您没有告诉编译器实例化的List
实际上是什么。另一方面,new ArrayList<A>()
会有意义。
答案 2 :(得分:1)
只需List<A>
就可以了,它允许在列表中实现A的对象以及列表中的所有对象实现A
答案 3 :(得分:0)
我认为你在寻找:
List<? super A> myList = new ArrayList<A>();
答案 4 :(得分:0)
你想要
列表&lt; A&gt; collection = new ArrayList&lt; A&gt; ();
通过使用通配符,您可以抑制编译器的信息。你说你希望能够同时读写'List'。通用'? super A'允许您写入集合但不能从中读取。通用'? extends A'允许您从集合中读取但不写入它。在通用参数中加上'A'可以让您读取和写入集合。请参阅Joshua Bloch在http://java.sun.com/docs/books/effective/generics.pdf上关于泛型的开创性 Effective Java 的免费章节。