【问题标题】:Java using GenericsJava 使用泛型
【发布时间】:2014-03-03 15:23:29
【问题描述】:

我有一个这样的接口A:

public interface A{
    void myFirstMethod();
    void mySecondMethod();
}

然后我就有了这个课程:

public class MyClass{
    private List<? extends A> elements;

    public MyClass(){
        A obj = new A(){
            @Override
            public void myFirstMethod(){
              //SOME CODE
            }
            @Override
            public void mySecondMethod(){
              //SOME CODE
            }
        };
        elements.add(obj);
    }
}

我以前没有使用过泛型(只有List&lt;String&gt;... 之类的东西)所以我不明白为什么这段代码不能编译。更准确地说,我在elements.add(obj); 行收到一个错误,表明方法 add 不适用于这些参数。

编辑: 我已经更改了代码,现在 elements.add(obj) 可以正常编译,但我还有另一个问题。

public class MyClass{
    private List<A> elements;

    public MyClass(List<A> elements){
        this.elements = elements;
        elements.add(obj);
    }
}

当我尝试这样做时,它无法编译。

//A1 implements A
List<A1> list = new ArrayList<A1>();
MyClass(list);

我该如何解决这个问题?

【问题讨论】:

    标签: java generics


    【解决方案1】:

    假设您有两个子类:

    class A1 implements A {...}
    class A2 implements A {...}
    

    那么你可以写:

    List<? extends A> elements = new ArrayList<A1>(); // a list of A1
    

    但这不应该编译:

    elements.add(new A2()); //oops: an A2 is not an A1
    

    因此,除了null 之外,您不能向List&lt;? extends A&gt; 添加任何内容,因为您不知道它是什么实际的泛型类型。换句话说,? extends A 表示A(或A 本身)的一个特定但未知的子类型。

    在您的情况下,List&lt;A&gt; 可能会达到您的预期 - 您可以向其中添加一些 A1s 和一些 A2s。

    【讨论】:

    • 换句话说:? 表示“未知”,而不是“任何”。
    • 没错;符号List&lt;? extends A&gt; 表示它是一些特定 但未知 类型的List。它确实不意味着列表可以包含扩展A的不同类型对象的混合;这意味着该列表包含扩展A 的某种确定类型的对象,但您不知道实际类型是什么。
    • 只是跟进它,我理解,但只是尝试了一些奇怪的东西,比如List&lt;? extends A&gt; elements = new ArrayList&lt;A&gt;(); 这行工作正常,但是当我尝试添加 A1 的对象时,elements.add(new A1()); 再次显示错误。我可以理解这个错误,但我的问题是为什么 Java 首先允许我写第一行之类的东西。new ArrayList&lt;A&gt;();
    • 如果你想在 A 类型的泛型集合中添加一些东西,请使用 List&lt;? super A&gt;。
    • @sakura 是的,这行不通,正是因为我们正在解释。编译器查看变量elements 的类型,即List&lt;? extends A&gt;。仅从该类型来看,编译器不知道列表中元素的确切类型。它只知道它们是扩展A 的未知类型。因为它不知道真正的类型是什么,所以你不能在列表中添加任何东西——因为编译器不可能判断你尝试输入的内容是否是有效的类型。用new ArrayList&lt;A&gt; 初始化变量并不重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多