考虑以下代码:
public class TreeNode<T extends TreeNode<T, E>, E> {
protected T parent;
protected E data;
protected List<T> children = new ArrayList<T>();
public TreeNode(T parent, E data) {
this.parent = parent;
this.data = data;
}
public T getRoot() {
if (parent == null) {
return this; //<---- Problem is here!
} else {
return getParent().getRoot();
}
}
public T getParent() {
if (parent == null) {
throw new RuntimeException("This already the parent!");
} else {
return parent;
}
}
}
/*
incompatible types
required: T
found: TreeNode<T,E>
*/
如何解决这个问题并使我的代码正常工作?
答案 0 :(得分:2)
您想使用所谓的getThis() trick。声明一个像这样的新方法:
/** Subclasses must implement this method as {@code return this;} */
protected abstract T getThis();
然后,当您需要使用this
时,只需拨打getThis()
即可。作为旁注,在@Michael Williamson的回答中实现这种方法会使像BadNode
这样的类混淆,从而使得首先编写这样一个类更难(这是一件好事)。
答案 1 :(得分:1)
不保证类型T与类本身的类型相同,因此您需要向不编译的行添加强制转换:
public T getRoot() {
if (parent == null) {
return (T)this;
} else {
return getParent();
}
}
举一个简单的代码示例,它将公开输入错误:
public class GoodNode extends TreeNode<GoodNode, Integer> {
public GoodNode(GoodNode parent, Integer data) {
super(parent, data);
}
}
public class BadNode extends TreeNode<GoodNode, Integer> {
public BadNode(GoodNode parent, Integer data) {
super(parent, data);
}
public static void main(String[] args) {
GoodNode node = new BadNode(null, null).getRoot();
}
}
运行BadNode.main导致输入错误,因为BadNode(null,null).getRoot()返回BadNode类的对象(因为它没有父级),但是因为BadNode扩展了TreeNode&lt; GoodNode,Integer&gt;,返回类型getRoot()是GoodNode。由于BadNode无法强制转换为GoodNode,因此存在类强制转换异常:
Exception in thread "main" java.lang.ClassCastException: BadNode cannot be cast to GoodNode
at BadNode.main(BadNode.java:7)
答案 2 :(得分:1)
也许你想要“过于通用”?
public class TreeNode<E> {
protected TreeNode<E> parent;
protected E data;
protected List<TreeNode<E>> children = new ArrayList<TreeNode<E>>();
public TreeNode(T parent, E data) {
this.parent = parent;
this.data = data;
}
public TreeNode<E> getRoot() {
if (parent == null) {
return this;
} else {
return getParent(); // <--- ???
}
}
...
}
BTW:您可能想要调用parent.getRoot()而不是getParent()的内容。
答案 3 :(得分:1)
为什么在extends子句中使用原始类型?这可能会阻碍类型推断。 请尝试以下方法:
public class TreeNode<T extends TreeNode<T,E>, E> {