1

我有 java 泛型相关的问题

我有Container如下调用的父母类:容器可以包含其他容器和Services. 服务类扩展了 Container,但只能包含ServiceMembers也扩展 Container 的类。

即使在 Services 类中我覆盖了父类的getElements()方法并返回也是 Container 类的子类的元素的 ArrayList,下面的代码也不起作用。

关于如何让它工作的任何想法,或者我只是以错误的方式使用它?

public class Container
{
   protected ArrayList<Container> elements = new ArrayList<Container>();

   public ArrayList<Container> getElements()
   {
   }
}

public class Service extends Container
{
  public ArrayList<ServiceMember> getElements()
  {
  }
}
4

3 回答 3

1

我认为您只需要Container像这样修改类:

public class Container<T extends Container> {
   protected List<T> elements = new ArrayList<T>();

   public List<T> getElements() {
       return elements;  
   }
}

这将允许您使用Container类(或自身)的所有子类对其进行参数化。

该类Service将如下所示:

public class Service extends Container<Service> {

}

最后,您可以像这样实例化这些类的对象:

Service s = new Service();
ArrayList<Service> elements = s.getElements();

Container<Container> c = new Container<Container>();
ArrayList<Container> els = c.getElements();

//adding an element to each of the lists:
c.getElements().add(new Container<Container>());
System.out.println(c.getElements().size());

s.getElements().add(new Service());
System.out.println(s.getElements().size());

无论如何,我建议您在设计上仔细考虑,因为将原始类与泛型混合是不安全且令人困惑的。

于 2013-05-20T01:47:09.087 回答
1

即使在 Services 类中我覆盖了父类的 getElements() 方法并返回也是 Container 类的子类的元素的 ArrayList,下面的代码也不起作用。

这是不正确的。由于类型擦除 ArrayList<ServiceMember>不考虑覆盖getElements()方法所需的协变返回。

覆盖如下。您不会失去多态性,它仍然会发生,因为它取决于Object's 的类型(动态;在运行时)而不是其引用的类型(静态;在编译时)。

public class Service extends Container
{
  public ArrayList<Container> getElements()
  {
    // declare superclass Container
    ArrayList<Container> elements = new ArrayList<Container>();

    // but add subclass ServiceMember
    elements.add(new ServiceMember());

    return elements;
  }
}
于 2013-05-20T01:41:59.907 回答
-1

您需要键入 Container, 以指示所包含事物的类型:

public class Container<T extends Container<T>> {
    private List<T> elements = new ArrayList<T>();

    public List<T> getElements() {
        return elements;
    }
}

public class Service extends Container<Service> {
}

笔记:

  • 该类型T extends Container<T>似乎扩展了自身,但这是您指定它的方式,以避免原始 Container 类型
  • 该列表是私有的:子类应该简单地通过 getter 访问它
  • 使用抽象类型List而不是具体实现ArrayList,符合良好实践
于 2013-05-20T02:07:19.857 回答