我正在使用算法第四版(Sedgewick)并且对一些似乎要求为非静态节点实现静态方法的链表练习感到困惑。例如,
1.3.27 编写方法
max()
,该方法引用第一个节点 链表作为参数并返回最大键的值 列表。假设所有键都是正整数,并返回0
if 列表是空的。
或
1.3.31 实现嵌套类DoubleNode以构建双向链表, 其中每个节点包含对其前面的项目的引用 在列表中跟随它的项目(如果没有这样的项目,则为
null
)。然后 为以下任务实现静态方法:插入 开始,插入到最后,从头开始删除,从中删除 结束,在给定节点之前插入,在给定节点之后插入,以及 删除给定节点。
据我了解(并通过SO答案here和here确认),这是不可能的。正如所料,如果我尝试在超类中编写静态方法,Eclipse会出错:
public class DoublyLinkedList<Item> {
public static void insertStart(DoubleNode first) {
// implementation
}
private class DoubleNode {
Item item;
DoubleNode next;
DoubleNode previous;
}
}
(给出错误Cannot make a static reference to the non-static type DoubleNode
);或者在内部阶级:
public class DoublyLinkedList<Item> {
private class DoubleNode {
Item item;
DoubleNode next;
DoubleNode previous;
public static void insertStart(DoubleNode first) {
// implementation
}
}
}
(给出错误The method insertStart cannot be declared static; static methods can only be declared in a static or top level type
)。
我可以为DoublyLinkedList
类编写所需的方法作为实例方法,这对我来说似乎是最自然的。
然而,我觉得我可能会错过这里重要的事情。作者明确指出方法应该是静态的,并且还建议将第一个节点作为参数引用(这对于实例方法是不必要的,因为该类将具有第一个节点的实例变量)。我错过了什么?
答案 0 :(得分:4)
您可以将嵌套类设为static
。您将失去拥有封闭父类实例的约束,但它将允许您从静态方法操作DoubleNode
:
// This will compile
public class DoublyLinkedList<Item> {
public static <T> void insertStart(DoublyLinkedList<T> list, DoubleNode<T> first) {
// implementation
}
private static class DoubleNode<E> {
E item;
DoubleNode<E> next;
DoubleNode<E> previous;
}
}
这里要注意两点:正如您所看到的,当使内部类静态时,您需要为其提供自己的类型参数(在本例中为E
)。在您的代码中,您不需要这样做,因为任何DoubleNode
实例都保证包含DoublyLinkedList
实例,该实例已确定Item
将是什么。
其次,您需要为静态方法引入一个类型参数(&#34; <T>
&#34;),这样您就可以为两个参数强制执行相同的泛型类型。你也可以这样做并侥幸逃脱:
public static void insertStart(DoublyLinkedList<?> list, DoubleNode<?> first) {
...
}
如果您想知道,这也是在JDK LinkedList
实施中的完成方式:
// Source : Oracle JDK 1.7.0_67 lib - inside LinkedList class
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
作为旁注,我同意将这些方法作为实例成员编写更为自然;它是如何在OOP库中完成的。我没有Sedgewick的书副本,但看起来他试图同时教你嵌套类操作和列表实现;)