这或多或少是在 Java 中拥有一个接口的唯一方法,该接口带有引用实现类本身的方法。因此,例如,您可能会编写一个二叉树节点接口:
interface TreeNode<N extends TreeNode<N>> {
N getLeftChild();
N getRightChild();
void setLeftChild(N node);
void setRightChild(N node);
}
然后你有像
class TreeNodeWithInt extends TreeNode<TreeNodeWithInt> {
int value;
TreeNodeWithInt leftChild;
TreeNodeWithInt rightChild;
public TreeNodeWithInt getLeftChild() { return leftChild; }
public void setLeftChild(TreeNodeWithInt newLeft) { leftChild = newLeft; }
...
}
如果我们没有N
类型参数,您将被迫编写不安全的代码,例如
class TreeNodeWithInt extends TreeNode {
int value;
TreeNodeWithInt leftChild;
TreeNodeWithInt rightChild;
public void setLeftChild(TreeNode node) {
// note the dangerous cast!
leftChild = (TreeNodeWithInt) node;
}
}
这里的关键问题是,当接口描述方法的输入和返回类型时,不允许引用实现接口的类的类型。因此,您包含一个“自我”泛型类型参数。这是广泛使用泛型的代码中相对常见的习惯用法。
正如您已经正确识别的那样,它经常与Comparable
特定一起使用,因为您应该只能将对象与相同类型的其他对象进行比较。实际上,Collections.sort
被指定为List<T>
where T extends Comparable<? super T>
,这意味着它至少与 type 的其他值T
相当,但也可能与其他值相当。T
(最后,正如你所料——因为这是实现这种行为的唯一方法,所以它不是“好”或“坏”的做法。也就是说,该技术的目标是避免编写在没有警告的情况下编译但可以结束的方法up throwing ClassCastException
,这本身就是一个好习惯。)