3

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

这是我的代码

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

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

但是当我尝试这样做时:

myValidationObjects.add(email);

我得到:

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

两者EmailAddress实施验证。

根据this document,我应该能够同时使用extends接口和子类。

4

4 回答 4

7

List<? extends Validation> myValidationObjects

不正确的阅读

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

正确阅读

"myValidationObjects可以是扩展 的任何类型的列表Validation。例如,它可以是 aList<RangeValidation>或 a List<RegexValidation>。"

由于没有对象可以合法地添加到 aList<RangeValidation>和 aList<RegexValidation>中,Java 会阻止您调用add这种类型的变量。

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

于 2013-01-04T20:38:04.123 回答
5

您可以使用:

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

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

于 2013-01-04T20:35:16.247 回答
2

声明ArrayList<? extends Validation>意味着一个未知类的列表,该类扩展ValidationEmail与这个未知类不兼容。

您可以使用ArrayList<Validation>您的列表。

于 2013-01-04T20:37:12.843 回答
2

如果泛型类的Tis <? extends Foo>,那么您可以传递给采用的方法的唯一东西Tnull-不是任何扩展的子类Foo

原因是这List<? extends Validation>并不意味着“扩展验证的事物列表”。您只需List<Validation>. 相反,它的意思是“某种类型的列表,使得该类型扩展了 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。

于 2013-01-04T20:37:57.947 回答