如何避免在java中自引用类型安全接口的参数类型警告?

时间:2010-08-03 05:04:50

标签: java generics tree

我正在使用java中的树,我有一个带有自引用的简单无序树的以下接口:

public interface Node<N extends Node> {

  public N getParent();
  public void setParent(N parent);

  public Collection<N> getChildren();

  public void addChild(N node);
  public void removeChild(N node);

  public N getRootNode();

  ... more ...
}

当然,我们的想法是创建一个类型安全的节点

  public abstract class ParentChildNode<E extends Node> implements Node<E> {

真正让我烦恼的问题是我得到的警告:

ParentChild is a raw type. References to generic type Node<N> should be parameterized

warning on this line:

public interface Node<N extends Node> {

warning on this line:

    public abstract class ParentChildNode<E extends ParentChild> implements ParentChild<E>  

我能做到:

public interface Node<N extends Node<?>> {

但我担心我会进入 yuckness 领域。我可以压制警告但不允许在我工作的地方。

有什么建议吗?我注意到java.util collections API在任何地方都没有任何警告。

提前致谢

2 个答案:

答案 0 :(得分:3)

这样的事情(与Enum类的声明平行):

public interface Node<N extends Node<N>> {

  public N getParent();
  public void setParent(N parent);

  public Collection<N> getChildren();

  public void addChild(N node);
  public void removeChild(N node);

  public N getRootNode();

  ... more ...
}

public abstract class ParentChildNode implements Node<ParentChildNode> {

答案 1 :(得分:1)

你的类型是无限递归的。您的所有节点都是Node<Node<Node<Node<…>>>>类型或某些同样无限的子类型。 Java的泛型不足以处理这些事情。

此外,如果你有这些节点的树,根的类型是什么?它没有父母。我想你可以有NullNode<GodKnowsWhat>类型,但这只是推迟了问题。我想root可以简单地将null作为父级返回,但这会颠覆整个层次结构。

你能得到什么:我到目前为止:

public interface Node {
    public Collection<ChildNode<Node>> getChildren();

    public void addChild(ChildNode<Node> node);
    public void removeChild(ChildNode<Node> node);
}

public interface ChildNode<Parent> extends Node {
    public Parent getParent();
    public void setParent(Parent parent);
}

但是Node方法的类型是错误的。你不能用Java做到这一点。如果您真的想,请尝试Scala。它在JVM上运行,它的类型系统要复杂得多;我相当肯定它会允许你需要的那种类型的递归。此外,您可以能够在C ++中将其拉出来。 C ++也有一个功能更强大的类型系统,但我还没有用它来知道它是否会让你或多或少地用这些术语来做这件事。