Java 层次结构和泛型

Java 层次结构和泛型,java,generics,Java,Generics,在我的应用程序中,我有一个主要基于两个类层次结构的模型:容器和元素。容器中包含元素的列表引用。例如,BR>考虑java类子,即“代码>父/代码>子类型>代码> EngeleStave,是代码>元素Enthele的子类型。元素被用作列表的类型参数,我希望每个容器都可以从列表中添加、删除和获取元素。这些列表应尽可能严格,即应包含放置在同一层次结构级别的元素(Child-ElementChild) 我知道List和List没有子类型关系,有没有比只创建两个不同的列表更好的方法(List在Parent和

在我的应用程序中,我有一个主要基于两个类层次结构的模型:容器和元素。容器中包含元素的列表引用。例如,BR>考虑java类<代码>子<代码>,即“代码>父/代码>子类型>代码> EngeleStave<代码>,是代码>元素Enthele<代码>的子类型。元素被用作列表的类型参数,我希望每个容器都可以从列表中添加、删除和获取元素。这些列表应尽可能严格,即应包含放置在同一层次结构级别的元素(
Child
-
ElementChild

我知道
List
List
没有子类型关系,有没有比只创建两个不同的列表更好的方法(
List
Parent
List
Child
中)

在下面的示例中,我使用了一个继承列表来说明我的意思,但显然它没有编译:

public class Parent {

    protected List<ElementParent> list;

    public Parent () {
        list = new ArrayList<ElementParent>();
    }

    public List<ElementParent> getList() {
        return list;
    }

    public void add(ElementParent element) {
        list.add(element);
    }

    public void remove (ElementParent element) {
        list.remove(element);
    }

    public void setList(List<ElementParent> list) {
        this.list = list;
    }
}

public class Child extends Parent {


        public Child() {
            list = new ArrayList<ElementChild>(); // does not compile
        }

        public List<ElementChild> getList() { //does not compile
            return list;
        }

        public void add(ElementChild element) {
            list.add(element);
        }

        public void remove (ElementChild element) {
            list.remove(element);
        }

        public void setList(List<ElementChild> list) { //does not compile
            this.list = list;
        }

}
公共类父类{
受保护名单;
公共父级(){
列表=新的ArrayList();
}
公共列表getList(){
退货清单;
}
公共void添加(元素父元素){
列表。添加(元素);
}
删除公共void(ElementParent元素){
列表。删除(元素);
}
公共无效集合列表(列表){
this.list=列表;
}
}
公共类子级扩展父级{
公共儿童(){
list=new ArrayList();//未编译
}
public List getList(){//未编译
退货清单;
}
公共void添加(ElementChild元素){
列表。添加(元素);
}
公共无效删除(ElementChild元素){
列表。删除(元素);
}
public void setList(List List){//未编译
this.list=列表;
}
}

您的问题说明了为什么
List
List
不存在子类型关系

由于
Child扩展了Parent
Parent::add(ElementParent-element)
方法存在,因此它被继承到
Child

现在你可以写:

ElementParent ep = ...;
Child child = ...;
child.add(ep); //perfectly legal
但那又有什么用呢?是否将
ElementParent
添加到
ElementChild
s的列表中?这就是为什么
List
List
不存在子类型关系的原因

那么如何解决你的问题呢


通配符在这里可能有帮助,例如
List
List
都是
List您的问题说明了为什么
List
List
不在子类型关系中

由于
Child扩展了Parent
Parent::add(ElementParent-element)
方法存在,因此它被继承到
Child

现在你可以写:

ElementParent ep = ...;
Child child = ...;
child.add(ep); //perfectly legal
但那又有什么用呢?是否将
ElementParent
添加到
ElementChild
s的列表中?这就是为什么
List
List
不存在子类型关系的原因

那么如何解决你的问题呢


通配符在这里可能有帮助,例如
List
List
都是
List您的问题说明了为什么
List
List
不在子类型关系中

由于
Child扩展了Parent
Parent::add(ElementParent-element)
方法存在,因此它被继承到
Child

现在你可以写:

ElementParent ep = ...;
Child child = ...;
child.add(ep); //perfectly legal
但那又有什么用呢?是否将
ElementParent
添加到
ElementChild
s的列表中?这就是为什么
List
List
不存在子类型关系的原因

那么如何解决你的问题呢


通配符在这里可能有帮助,例如
List
List
都是
List您的问题说明了为什么
List
List
不在子类型关系中

由于
Child扩展了Parent
Parent::add(ElementParent-element)
方法存在,因此它被继承到
Child

现在你可以写:

ElementParent ep = ...;
Child child = ...;
child.add(ep); //perfectly legal
但那又有什么用呢?是否将
ElementParent
添加到
ElementChild
s的列表中?这就是为什么
List
List
不存在子类型关系的原因

那么如何解决你的问题呢


通配符在这里可能有帮助,例如
List
List
都是
List这是一个棘手的问题,称为协变子类型。简而言之,这意味着当您扩展(也称为子类化)一个类并重写其某些方法时,您无法更改这些方法的参数类型。如果允许,编译器将无法保证Java的类型安全

A好的,解决问题的唯一办法是更多地依赖泛型。具体来说,您需要定义一个在元素类型和列表类型上都参数化的类:

public class Base<E, L extends List<E>> {

  protected L list;

  public Base(L l) { list = l; }     

  public L getList() { return list; }
  public void add(E element) { list.add(element); }
  public void remove(E element) { list.remove(element); }
  public void setList(L list) { this.list = list; }
}

这是一个棘手的问题,称为协变子类型。简而言之,这意味着当您扩展(也称为子类化)一个类并重写其某些方法时,您无法更改这些方法的参数类型。如果允许,编译器将无法保证Java的类型安全

A好的,解决问题的唯一办法是更多地依赖泛型。具体来说,您需要定义一个在元素类型和列表类型上都参数化的类:

public class Base<E, L extends List<E>> {

  protected L list;

  public Base(L l) { list = l; }     

  public L getList() { return list; }
  public void add(E element) { list.add(element); }
  public void remove(E element) { list.remove(element); }
  public void setList(L list) { this.list = list; }
}

这是一个棘手的问题,称为协变子类型。简而言之,这意味着当您扩展(也称为子类化)一个类并重写其某些方法时,您无法更改这些方法的参数类型。如果允许,编译器将无法保证Java的类型安全

A好的,解决问题的唯一办法是更多地依赖泛型。具体地说,哟