将子类的ArrayList传递给一个采用超类ArrayList的构造函数?

时间:2017-05-27 21:46:11

标签: java polymorphism

好的,所以我正在为这所大学的这个项目工作,我想我在这里做错了什么,我猜我还没有理解java子类化和类继承。

我已经用这个小形式改写了我的问题。

    class SuperClass {

        int dunno;

        public SuperClass(int dunno) {
            this.dunno = dunno;
        }
    }

    class SubClass extends SuperClass {

        int duncare;

        public SubClass(int dunno, int duncare) {
            super(dunno);
            this.duncare = duncare;
        }
    }

    class VeryBigClass {

        ArrayList<SuperClass> superList;

        public VeryBigClass(ArrayList<SuperClass> superList) {
            this.superList = superList;
        }
    }

    public void main(String[] args) {

        new VeryBigClass(new ArrayList<SubClass>()); // this is the problematic line

    }

}

简单地说,我编写了许多扩展一个通用类的类,并且在许多地方我使用超类(一般类)进行操作,而不是以相同的方式逐个处理每个子类。 。

但是我无法创建我需要的类的实例,因为构造函数将超类作为参数。我甚至不知道如何施展它,因为new VeryBigClass(new (ArrayList<SuperClass>)ArrayList<SubClass>());显然是错误的。另外,这些实例的构建将由json库在某个时刻处理,所以我宁愿不做这些花哨的东西...

3 个答案:

答案 0 :(得分:6)

如果你使用泛型,它应该工作得很好,与超类的列表不同,而不是子类列表,但通用解决了这个:

class VeryBigClass<T extends SuperClass> {

    ArrayList<T> superList;

    public VeryBigClass(ArrayList<T> superList) {
        this.superList = superList;
    }
}

答案 1 :(得分:4)

Java Tutorial在http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html

中解释了这一点

从底线开始,如果您有具有继承关系的类型,例如Sub extends Super作为泛型,那么会在包含它们的类中赋予继承关系:Foo<Sub>不是Foo<Super>的子类型。

原因是它违反了泛型类型所包含的类型的承诺,违反了Liskov Substitution原则。如果List<Sub>延长List<Super>,则执行此操作是合法的:

List<Sub> subs = new ArrayList<Sub>();
List<Super> supers = subs;

Super super = new Super();
supers.add(super);

哇!现在subsSuper类型的元素,完全非法!

因为ArrayList<Sub>不是List<Super>的子类型,所以当您调用

new VeryBigClass(new ArrayList<SubClass>());

您将参数传递给不合法的构造函数。

答案 2 :(得分:2)

您还可以使用通配符? extends super即任何扩展超级的类。

示例

class VeryBigClass {

    ArrayList<? extends SuperClass> superList;

    public VeryBigClass(ArrayList<? extends SuperClass> superList) {
        this.superList = superList;
    }
}