如何在一个列表中包含Base和Sub-Class的实例?

时间:2012-09-24 15:59:27

标签: java generics

我目前面临基础和子类的问题。

虽然将单个对象作为参数(单个方法),但编译器不会抱怨。

但如果涉及到列表,编译器会强制我将列表声明为<? extends Base>

之后我不再允许将基类型的对象添加到该列表中。

如何在一个列表中使用这两种类型(Base和Subclass)?

public class Generics {

    class Base {    }

    class Sub extends Base{     }

    interface I {
        public void list( List<Sub> list );
        public void single( Sub p);
    }

    class C implements I {
        public void list( List<Sub> list) {     }
        public void single( Sub p) {        }
    }

    void test() {
        C c = new C();
        c.single( new Sub() );
        c.list( new ArrayList<Base>() ); // The method list(List<Generics.Sub>) in the type Generics.C is not applicable for the arguments (ArrayList<Generics.Base>)

    }

    public static void main( String[] args) {
        Generics g = new Generics();
        g.test();
    }
}

3 个答案:

答案 0 :(得分:1)

只需将所有列表声明为

即可
List<Base> list;

然后,您可以添加Base个对象和任何子类的对象。

答案 1 :(得分:1)

变化:

public void list(List<Sub> list);

为:

public void list(List<? extends Base> list);

只使用List<Base>会给你编译错误,如下所示:

public static void main(String[] args) {
    List<Sub> subs = new ArrayList<Sub>();
    doSomethingWith(subs); // The method doSomethingWith(List<Base>) in the type Main is not applicable for the arguments (List<Sub>)
}

private static void doSomethingWith(List<Base> bases) {
    // Do something with bases
}

如果您要传递的只是List<Base>doSomethingWith,那么这一点没有实际意义,因为这不会给您带来编译错误。如果您要传递特定类型的列表(例如上面的List<Sub>),则需要将doSomethingWith更改为:

private static void doSomethingWith(List<? extends Base> bases) {

这解决了这个问题。你也可以在调用者控制杆上做这件事(但有点麻烦):

    List<Sub> subs = new ArrayList<Sub>();
    doSomethingWith(new ArrayList<Base>(subs));

通配符(?)方法的一个问题是您无法将新项添加到列表中。要做到这一点,你需要像:

private static <B extends Base> void doSomethingWith(List<B> bases) {

然后只将B个实例添加到bases

答案 2 :(得分:1)

以下是两种方法....

public void inTake(List<? extends Base> list){

}

public T extends Base void inTake(List<T> list){

}