我有一组类都实现了一个具有方法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类型中 不适用于参数(电子邮件)
Email
和Address
都会实施验证。
根据this document,我应该可以对接口和子类使用extends
。
答案 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。