【问题标题】:Java ArrayList of ? extends InterfaceJava ArrayList 的?扩展接口
【发布时间】:2012-12-19 07:49:23
【问题描述】:

我有一组类都实现了一个验证接口,该接口具有方法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 用于接口和子类。

【问题讨论】:

  • 为什么不使用ArrayList&lt;Validation&gt; 而没有任何extends
  • ? extends Validation 表示Validation 的一些特定但未知 子类。据编译器所知,它可能是与EmailAddress 完全无关的其他子类。

标签: java generics collections interface arraylist


【解决方案1】:

List&lt;? extends Validation&gt; myValidationObjects

读错

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

正确阅读

myValidationObjects 可以是扩展Validation 的任何类型的列表。例如,它可以是List&lt;RangeValidation&gt;List&lt;RegexValidation&gt;。”

由于没有对象可以合法地添加到List&lt;RangeValidation&gt;List&lt;RegexValidation&gt;,Java 会阻止您在此类变量上调用add

您的情况实际上更简单:您需要确定类型List&lt;Validation&gt;

【讨论】:

    【解决方案2】:

    你可以使用:

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

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

    【讨论】:

      【解决方案3】:

      声明ArrayList&lt;? extends Validation&gt; 表示扩展Validation 的未知类的列表。 Email 与这个未知类不兼容。

      您可以使用ArrayList&lt;Validation&gt; 作为您的列表。

      【讨论】:

        【解决方案4】:

        如果泛型类的T&lt;? extends Foo&gt;,那么您可以传递给采用T 的方法的唯一内容是null -- 不是任何扩展@987654325 的子类@。

        原因是List&lt;? extends Validation&gt; 并不意味着“扩展验证的事物列表”。您只需 List&lt;Validation&gt; 即可获得。相反,它的意思是“某种类型的列表,使得该类型扩展了 Validation。”

        这是一个微妙的区别,但基本上是List&lt;? extends T&gt;List&lt;T&gt; 的子类型,因此您希望能够向其中插入任何内容。想想这个案例:

        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。

        【讨论】:

          猜你喜欢
          • 2023-03-22
          • 2017-10-08
          • 2018-04-14
          • 2012-11-06
          • 2013-01-29
          • 2011-01-14
          • 2012-10-23
          • 2011-12-27
          • 2012-09-01
          相关资源
          最近更新 更多