Java ArrayList的?扩展接口

时间:2013-01-04 20:32:24

标签: java generics collections interface arraylist

我有一组类都实现了一个具有方法isValid()的验证接口。我想把一组对象 - 所有不同的类 - 放到一个ArrayList中,循环遍历它们并在每个对象上调用isValid()

这是我的代码

Email email = new email();
Address address = new Address();

ArrayList<? extends Validation> myValidationObjects = new ArrayList();

但是当我尝试做的时候:

myValidationObjects.add(email);

我明白了:

  

方法add(捕获#2-of?extends Validation)在ArrayList类型中    不适用于参数(电子邮件)

EmailAddress都会实施验证。

根据this document,我应该可以对接口和子类使用extends

4 个答案:

答案 0 :(得分:5)

您可以使用:

List<Validation> myValidationObjects = new ArrayList<>();           // Java 7
List<Validation> myValidationObjects = new ArrayList<Validation>(); // pre Java 7

现在,您可以将实现Validation的类的任何实例添加到该列表中。

答案 1 :(得分:5)

List<? extends Validation> myValidationObjects

读数不正确

myValidationObjects是扩展Validation的对象列表。”

正确阅读

myValidationObjects可以是展开Validation的任何类型的列表。例如,它可以是List<RangeValidation>List<RegexValidation>。”

由于没有对象可以合法地添加到List<RangeValidation>List<RegexValidation>,因此Java会阻止您对此类变量调用add

您的情况实际上更简单:您需要明确的类型List<Validation>

答案 2 :(得分:2)

声明ArrayList<? extends Validation>表示扩展Validation的未知类的列表。 Email与此未知类不兼容。

您可以将ArrayList<Validation>用于列表。

答案 3 :(得分:2)

如果通用类的T<? extends Foo>,那么您唯一可以传递给T的方法的是null - 不是任何扩展Foo的子类。

原因是List<? extends Validation>并不意味着“扩展验证的事项列表”。只需List<Validation>即可获得。相反,它意味着“某种类型的列表,以便该类型扩展验证。”

这是一个微妙的区别,但基本上我的想法是List<? extends T>List<T>的子类型,因此希望能够插入任何内容它。想想这个案子:

List<FooValidation> foos = new ArrayList<>();
List<? extends Validation> validations = foos; // this is allowed
validations.add(new BarValidation()); // not allowed! this is your question
FooValidation foo = foos.get(0);

如果允许第三行,那么最后一行将抛出ClassCastException。