【问题标题】:Static methods for operations on inner class内部类操作的静态方法
【发布时间】:2015-10-17 23:25:54
【问题描述】:

我正在研究算法第四版(Sedgewick),并且对一些似乎要求为非静态节点实现静态方法的链表练习感到困惑。例如,

1.3.27 编写一个方法max(),该方法引用a中的第一个节点 链表作为参数并返回最大键的值 名单。假设所有键都是正整数,如果返回0 列表为空。

1.3.31 实现一个嵌套类 DoubleNode 来构建双向链表, 其中每个节点都包含对它前面的项目的引用和 列表中它后面的项目(null,如果没有这样的项目)。然后 为以下任务实现静态方法:在 开始,插入末尾,从开头删除,从开头删除 最后,在给定节点之前插入,在给定节点之后插入,以及 删除给定的节点。

据我了解(并由 SO 回答 herehere 确认)这是不可能的。不出所料,如果我尝试在超类中编写静态方法,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 类的实例方法,这对我来说似乎是最自然的。

但是,我觉得我可能在这里错过了一些重要的事情。作者明确指出方法应该是静态的,并且还建议将第一个节点的引用作为参数(这对于实例方法来说是不必要的,因为该类将具有第一个节点的实例变量)。我错过了什么?

【问题讨论】:

    标签: java static linked-list static-methods inner-classes


    【解决方案1】:

    您可以将嵌套类设为static。您将失去拥有封闭父类实例的约束,但它将允许您从静态方法对DoubleNodes 进行操作:

    // 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 将是什么。

    其次,你需要为你的静态方法引入一个类型参数(“&lt;T&gt;”),这样你就可以对两个参数强制使用相同的泛型类型。你也可以这样做并侥幸逃脱:

    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 的书,但看起来他正试图同时教你嵌套类操作和列表实现;)

    【讨论】:

    • 谢谢。看 JDK 实现很有趣。在这种情况下,该约束的重要性是什么?
    • 约束是阻止您的代码成功编译的原因。它可以确保您不能使用变量来保存“独立”DoubleNode 对象,或者定义返回 DoubleNode 类型值的静态或外部方法。重点是鼓励封装(“将所有 DoubleNode 内容保留在 DoublyLinkedList 实例方法中”),但在这种情况下,它违反了“制作静态方法”声明。
    • 您可以在这里阅读关于各种嵌套类类型的基本介绍:docs.oracle.com/javase/tutorial/java/javaOO/nested.html
    • 好的。您原始答案中的代码无法编译 - 这似乎是Item 参数化的问题。我在第 4 行和第 9 行收到错误 Cannot make a static reference to the non-static type Item
    • 抱歉,我刚刚意识到您的整个列表类有一个Item 类型参数。我会在一分钟内纠正这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2012-05-27
    相关资源
    最近更新 更多