【问题标题】:Generic defined using an interface instead of class使用接口而不是类定义的泛型
【发布时间】:2011-10-31 17:17:22
【问题描述】:

如何指定我希望任何实现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" }) 以使编译器对警告保持沉默。

【问题讨论】:

    标签: java class generics inheritance interface


    【解决方案1】:

    要了解为什么实例化new ArrayList<? extends A>() 没有意义,实际上我们可以等效地创建一个具有任意类或接口Bnew ArrayList<B>()(甚至与您的任何对象都不相关的) ) 实现了A,并且生成的ArrayList 可以安全地分配给ArrayList<? extends A> 类型的变量。那么你可能会想,哦,这很愚蠢,因为我要放入其中的对象不是B类的,那怎么会一样呢?但它相同的,因为无论如何您都不能将任何内容放入Something<? extends A> 类型的引用中。这就是为什么创建 new ArrayList<? extends A>() 没有意义的原因。

    如何指定我想要任何实现 A 接口以类型安全的方式被允许在列表内部?一世 希望能够在所有对象上调用 A 的给定方法, 关于它们是什么类类型。

    这正是ArrayList<A> 的含义。它允许A 的所有实例(当然所有实现A 的对象都是A 的实例)并且您可以在它们上使用A 的任何方法。像这样的东西就是你想要的:

    List<A> myList = new ArrayList<A>();
    

    List&lt;? extends A&gt; 之类的东西仅在您将从其他代码中获取 List 对象,并且您不知道(或关心)他们创建它的通用参数究竟是什么的情况下使用。 (在这种情况下,您不能将对象放入 List。)这与您在此处的情况完全不同,正在创建 List 对象,因此您决定并因此确切地知道使用了什么通用参数.

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      我想你正在寻找:

      List<? super A> myList = new ArrayList<A>();
      
      1. 列表 extends A> myList ... 告诉编译器它是一些未指定类型的列表,而未指定类型扩展了 A。您不能将任何 A 放入此列表中,因为它可能不是正确的确切类型。编译器所知道的是,此列表中的任何对象都必须是 A。我认为您想要 List myList。这告诉编译器 List 是 A 扩展的某种未指定类型。现在编译器可以让我将任何 A 放入列表中。
      2. 新数组列表();完全错了。

      【讨论】:

      • 编译时,当您迭代对象时,您不能以类型安全的方式这样做。该列表返回Object。我想说A instance = myList.get(0);
      • ^ 这行得通,我想在使用带有泛型的接口时,您需要指定 &lt;? extends {interface}&gt;?可能不会!我的信息来自francisoud.blogspot.com/2007/09/…
      • 在类或方法声明的类型参数中写入T extends A 与在变量声明中写入? extends A 不同。前者是本文所展示的内容。
      • 没有必要。 extends A> 表示扩展 A 的一些未指定类型。它对于像 extends Runnable & Comparable> 您指定列表由实现 2 个或更多接口的元素组成。它对您的情况没有帮助。
      【解决方案4】:

      只需List&lt;A&gt; 就可以了,这允许在列表中实现 A 的对象以及列表中的所有对象都实现 A

      【讨论】:

        【解决方案5】:

        该问题与将类型参数绑定到接口无关,而是您无法使用通配符实例化参数化类型。 new ArrayList&lt;? extends A&gt;() 甚至 new ArrayList&lt;?&gt;() 没有意义,因为您没有告诉编译器实例化的 List 实际包含什么。另一方面,new ArrayList&lt;A&gt;() 是有意义的。

        【讨论】:

        • 所以你是说我的问题没有解决方案?你不能指定这个吗?
        • 当您实例化List 时,您必须准确指定它所包含的元素类型。这可能是new ArrayList&lt;A&gt;()new ArrayList&lt;Foo&gt;(),其中Foo 实现A。如果您需要更多帮助,我们需要查看导致您出现这种情况的代码。
        猜你喜欢
        • 2012-02-27
        • 2020-01-10
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 2019-07-21
        • 2015-01-18
        • 2020-03-22
        • 1970-01-01
        相关资源
        最近更新 更多