内部操作的静态方法 class
Static methods for operations on inner class
我正在学习 算法第四版 (Sedgewick),我对一些链表练习感到困惑,这些练习似乎要求为非静态节点。例如,
1.3.27 Write a method max()
that takes a reference to the first node in a
linked list as argument and returns the value of the maximum key in
the list. Assume that all keys are positive integers, and return 0
if
the list is empty.
或
1.3.31 Implement a nested class DoubleNode for building doubly-linked lists,
where each node contains a reference to the item preceding it and the
item following it in the list (null
if there is no such item). Then
implement static methods for the following tasks: insert at the
beginning, insert at the end, remove from the beginning, remove from
the end, insert before a given node, insert after a given node, and
remove a given node.
据我了解(并由 SO 回答 here and here 确认)这是不可能的。正如预期的那样,如果我尝试在 superclass:
中编写静态方法,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
);或者在内部 class:
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
class 编写所需的方法作为 实例方法 ,这对我来说似乎最自然。
但是,我觉得我可能在这里错过了一些重要的事情。作者明确指出方法应该是静态的,并且还建议将对第一个节点的引用作为参数(这对于实例方法来说是不必要的,因为 class 将为第一个节点提供一个实例变量) .我错过了什么?
您可以将嵌套的 class 设为 static
。您将失去拥有封闭父 class 实例的约束,但它将允许您从静态方法对 DoubleNode
s 进行操作:
// 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;
}
}
这里需要注意两件事:如您所见,当使内部 class 静态化时,您需要为其提供自己的类型参数(在本例中为 E
)。在你的代码中你不需要这样做,因为任何 DoubleNode
实例都保证有一个包含 DoublyLinkedList
的实例,它已经决定了 Item
是什么。
其次,您需要为静态方法引入一个类型参数 ("<T>
"),这样您就可以为两个参数强制使用相同的泛型类型。您也可以这样做并侥幸逃脱 :
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 的书,但看起来他正试图同时教你嵌套 class 操作和列表实现 ;)
我正在学习 算法第四版 (Sedgewick),我对一些链表练习感到困惑,这些练习似乎要求为非静态节点。例如,
1.3.27 Write a method
max()
that takes a reference to the first node in a linked list as argument and returns the value of the maximum key in the list. Assume that all keys are positive integers, and return0
if the list is empty.
或
1.3.31 Implement a nested class DoubleNode for building doubly-linked lists, where each node contains a reference to the item preceding it and the item following it in the list (
null
if there is no such item). Then implement static methods for the following tasks: insert at the beginning, insert at the end, remove from the beginning, remove from the end, insert before a given node, insert after a given node, and remove a given node.
据我了解(并由 SO 回答 here and here 确认)这是不可能的。正如预期的那样,如果我尝试在 superclass:
中编写静态方法,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
);或者在内部 class:
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
class 编写所需的方法作为 实例方法 ,这对我来说似乎最自然。
但是,我觉得我可能在这里错过了一些重要的事情。作者明确指出方法应该是静态的,并且还建议将对第一个节点的引用作为参数(这对于实例方法来说是不必要的,因为 class 将为第一个节点提供一个实例变量) .我错过了什么?
您可以将嵌套的 class 设为 static
。您将失去拥有封闭父 class 实例的约束,但它将允许您从静态方法对 DoubleNode
s 进行操作:
// 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;
}
}
这里需要注意两件事:如您所见,当使内部 class 静态化时,您需要为其提供自己的类型参数(在本例中为 E
)。在你的代码中你不需要这样做,因为任何 DoubleNode
实例都保证有一个包含 DoublyLinkedList
的实例,它已经决定了 Item
是什么。
其次,您需要为静态方法引入一个类型参数 ("<T>
"),这样您就可以为两个参数强制使用相同的泛型类型。您也可以这样做并侥幸逃脱 :
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 的书,但看起来他正试图同时教你嵌套 class 操作和列表实现 ;)