【问题标题】:Using a static inner class [duplicate]使用静态内部类[重复]
【发布时间】:2015-02-16 12:42:21
【问题描述】:

我有一个关于在以下代码中使用静态内部类的问题,改编自 Eckel 的 Thinking in Java 第 4 版(第 625 页)。

代码使用名为 Node.js 的静态内部类。当您创建堆栈结构时,您可以将节点推送到堆栈上并将它们弹出 - 到目前为止一切都很好。但是我很困惑为什么节点类是静态的?那不是意味着在 LinkedStack 类中只会创建一个 Node 吗?实际上,您如何/为什么可以将许多不同的节点推入堆栈,然后将它们弹出(这当然是堆栈应该做的)。其实你可以把private static class Node改成'private class Node`,也可以用……那Eckels为什么选择静态类Node呢?

在这个例子中,输入是三个词“Phasers”、“on”、“stun!”输出是“stun!”、“on”、“Phasers”。

public class LinkedStack<T> {

    //generic inner class node
    private static class Node<U> {

        U item;
        Node<U> next;
        Node() {
            item = null;
            next = null;
        }
        Node(U item, Node<U> next) {
            this.item = item;
            this.next = next;
        }
        boolean isDummyNode() {
            return item == null && next == null;
        }
    }

    //initialize top of stack as a dummy first node
    private Node<T> top = new Node<T>();

    public void push(T item) {
        top = new Node<T>(item, top);
    }

    public T pop() {
        T result = top.item;
        if(!top.isDummyNode())
            top = top.next;
        return result;
    }

    public static void main(String[] args) {
        LinkedStack<String> stack = new LinkedStack<String>();
        for(String s : "Phasers on stun!".split(" "))
            stack.push(s);
        String s;
        while((s = stack.pop()) != null)
            System.out.println(s);
    }

}

【问题讨论】:

  • 其他问题没有我的答案。另外,我显然正在阅读和研究,因为这些问题来自 Eckel 关于 Java 的书。我可以对您的决定提出上诉吗?
  • 我对为什么节点类是静态的感到困惑?这在重复的 Q/A 中有解释。 这不意味着在 LinkedStack 类中只会创建一个 Node 吗? 这是一个类,你可以创建一个类的许多实例,不管它是顶级类还是内部类(这是不是火箭科学)。 实际上您如何/为什么可以将许多不同的节点推入堆栈...它们是实例,您可以使它们按您的意愿运行。有了这一切,你的问题归结为为什么节点类是静态的?这可以通过阅读 dup 来回答。
  • @topsail:在上诉时,任何在 java 中拥有金徽章的用户都可以重新打开它。或编辑问题会将其发送到重新打开审核队列。但我认为 Luiggi 的链接答案应该可以解决您的问题,前提是您可以放弃对关键字 static 的错误理解。
  • @topsail 您将static class 与static 类的成员(字段或方法)混淆了。 static 类类似于顶级类,但在类中声明。为什么要这样做?好吧,假设您只是不希望您的 LinkedStack 类的客户可以任意创建 Node 并与它们一起玩,因此声明 public class 不是一个好主意,而将其声明为简单的 class (默认包)仍然可以访问同一包中的类,因此您可以将其声明为 LinkedStack 内的 private static class 以将 Node 的使用限制为仅限 LinkedStack。
  • @tgkprog 这是一个很好的例子来了解定义private static classes 的好处,请查看我上面的评论。

标签: java


【解决方案1】:

不,静态内部类是不需要封闭类型实例的类,当在方法或字段的上下文中使用时,它与静态不同。内部类的静态本质上使它们成为顶级类。当您声明一个非静态内部类时,它具有对封闭类型的实例字段和方法的隐式访问,因此需要所述类型的实例。静态类没有那么奢侈,因此不需要封闭类型的实例。

【讨论】:

  • 但是我们显然不能在没有实例化的情况下使用 LinkedStack?那么这里有静态节点不是没有意义(或其他方面没有意义)吗?
  • 所以static class Node 嵌套在 LinkedStack 中意味着你可以拥有很多 Node 对象?但是static class Node不嵌套在LinkedStack中就意味着只有一个节点?
【解决方案2】:

静态内部类与外部类(在本例中为LinkedStack)相关联,而不是与它的实例相关联。对于非静态内部类,应该有一个外部类的封闭实例。如果Node 不是静态的,则意味着要存在Node 的任何实例,必须有一个包含该实例的LinkedStack 实例。

将Node 类作为静态类使其更像是一个顶级类,不绑定到外部类的实例。因此,其他类可以创建Node 的实例,而无需创建任何LinkedStack 的实例。

有关差异的更多详细信息,请参阅 Java 教程中的 Nested classes。

【讨论】:

  • 好吧,你的回答和 Mark W 的回答很相似。我的想法是 Eckel 的代码不好,因为不想为这个类定义节点然后打开它们用于其他任何地方的任何用途。也许他这样做只是因为教科书的例子更容易?如果 Node 是你可以在 LinkedStack 之外制作的东西,那么将它们变成 LinkedStack 的内部类似乎很奇怪。无论如何,这是我目前的想法。
  • @topsail Node 类根本就不是内部类。根据定义,内部类是非静态嵌套类。您可以将LinkedStack 视为为Node 提供命名空间。它只是一个嵌套在LinkedStack 中的顶级类。
  • 谢谢。我的最终结论(不一定正确)是静态嵌套类在这里没有特别的原因。无论如何它都是私有的,因此不能在 LinkedStack 类之外创建节点。因此,嵌套的静态类不会像(非静态)内部类那样做。加上一个(非静态)内部类可以访问外部类的泛型类型参数(T),您不需要静态嵌套类必须使用的额外泛型。
猜你喜欢
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多