泛型:在集合中添加子类对象的问题

时间:2013-08-21 02:38:51

标签: java generics

所以我一直在阅读Oracle提供的泛型教程:http://docs.oracle.com/javase/tutorial/java/generics/

我已经尝试运行自己的示例以确保我了解如何使用泛型。我有以下代码:

import java.util.*;

public class Generics {
    class NaturalNumber {
        private int i;

        public NaturalNumber(int i) { this.i = i; }
    }
    class EvenNumber extends NaturalNumber {
        public EvenNumber(int i) { 
            super(i);
        }
    }    
    public static void main(String[] args) {
        Collection<? extends NaturalNumber> c = new ArrayList<>();
        c.add(new EvenNumber(2)); //this line produces a compile time error     
    }
}

我的目标是能够将任何NaturalNumber子类型的对象添加到Collection c中。我不确定为什么这不起作用,阅读Oracle的教程也没有启发我。

3 个答案:

答案 0 :(得分:7)

当您拥有? extends NaturalNumber时,该参数可能是NaturalNumber的某些其他子类,与EvenNumber无关。例如,

Collection<? extends NaturalNumber> c = new ArrayList<OtherNaturalNumber>();
如果OtherNaturalNumber延长NaturalNumber,则

有效。

因此,您无法在列表中添加EvenNumber实例。你可以使用这个声明:

Collection<NaturalNumber> c = new ArrayList<>();

允许您添加任何NaturalNumber个实例(包括EvenNumber)。

另一方面,你可能想要制作那些嵌套的类static(或者根本不嵌套它们)。

答案 1 :(得分:1)

首先Collection<? extends NaturalNumber>应为Collection<NaturalNumber>EvenNumber(或任何NaturalNumber或[{1}}的子类型)的实例可以通过这种方式放入集合中。

基本上NaturalNumber表示Collection<? extends NaturalNumber>的类型参数类型扩展为Collection。所以说NaturalNumberclass OddNumber extends NaturalNumber的类型参数的类型可能是CollectionOddNumber无法安全地转换为。{/ p>

然而,还有另一个编译器错误。要在静态上下文中使用,或EvenNumber每个内部类main(String[])NaturalNumber都需要在每个类声明上放置修饰符EvenNumber

答案 2 :(得分:0)

你的问题是你告诉编译器Collection的元素类型可以是extends NaturalNumber的任何类型,但是你试图插入一个对象进去。就编译器而言,cCollection<OddNumber>,您刚刚添加了EvenNumber