Using a static inner class
我有一个关于静态内部类在下面的代码中使用的问题,它是从Java第四版(第625页)中的ECKEL思想改编而来的。
代码使用一个名为node的静态内部类。当您创建一个堆栈结构时,您可以将节点推到堆栈上,然后将它们弹出——目前为止还不错。但是我很困惑为什么节点类是静态的?这不意味着LinkedStack类中只会创建一个节点吗?实际上,您可以将许多不同的节点推到堆栈上,然后将它们弹出(当然,堆栈应该做什么)。实际上,您可以将private static class Node更改为'private class node',它也可以工作…那么Eckels为什么选择静态类节点呢?
在本例中,输入的是三个字"phasers"、"on"、"stun!"输出是"震惊!","开","相位器"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| 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 );
}
} |
- 其他问题没有答案。此外,我显然阅读和研究,因为问题来自埃克尔的关于Java的书。我可以上诉你的决定吗?
- 我很困惑为什么节点类是静态的?这在重复的Q/A中得到了解释。这是否意味着在LinkedStack类中只会创建一个节点?它是一个类,您可以创建一个类的许多实例,尽管它是顶级的或内部类(这不是火箭科学)。如何/为什么事实上您可以将许多不同的节点推送到堆栈上…它们是实例,你可以让它们按照你的意愿行事。有了这些,您的问题可以归结为为什么节点类是静态的?可以通过读DUP来回答。
- TopSave:在吸引人的情况下,任何拥有Java徽章的用户都可以重新打开它。或者编辑问题会将其发送到重新打开的审阅队列。但我认为,如果你能放弃对关键词static的错误理解,Luiggi的链接答案应该能够解决你的问题。
- 我刚刚又读了一遍:)我觉得奇怪的是静态类不应该有很多实例。这不是重点吗?你说你可以有一个类的许多实例,但是我们不能创建许多数学对象,对吗?我要求澄清一下,以便我能理解这一点。你们帮了我很多忙,有一位专家能准确地指出我所缺少的东西,这真的会帮助我。
- @托普赛:不,这不是重点。静态只意味着没有对父类的对象的引用。
- @TopSeal您将static class与类的static成员(字段或方法)混淆。static类类似于顶级类,但在类内声明。为什么要这样做?好吧,假设你只是不希望你的LinkedStack类的客户可以随意创建一个Node并与他们一起玩,所以声明public class不是一个好主意,并且声明它为一个简单的class包(默认包)仍然使同一包中的类可以访问它,所以你声明它为private static classinsi。de LinkedStack仅限Node的使用。
- 在我的应用程序编程中,从来没有必要创建一个静态的内部类。喜欢做一个顶级的班级。我的建议是在你的研究中转到更有用的主题,比如TDD,网络应用,参见…codingbat.com。
- @tgkprog这是一个很好的例子来理解定义private static classes的好处,只需查看我在您上面的评论。
- 可以。你们帮了大忙。我还在努力学习这个。最近两周我一直在用埃克尔斯书学习Java五小时。能直接问一个我不懂的问题是有帮助的。所有的学生——即使是努力工作的学生也有问题要问。所以我才来这里。你们是最好的。在这种情况下,我认为Eckel希望嵌套类能够访问push和pop方法(可能只是为了方便编写关于泛型的示例,而不是嵌套类)。但它可能不是最好的设计(?).
- 是的,以前听过。我想我从未觉得我的客户会做他们不该做的事情。主要是因为它的应用程序代码。不打开SRC库。有了反射,你就不能在运行时更改访问权限了吗?
- 对我来说,这是一个很好的设计。只要你只向你的客户提供必要的元素,就没有什么错。注意,LinkedStack的客户永远不会直接与Node交互。有些情况下,您只想将此static class或static interface声明为public,如Map.Entry。
- @tgkprog是的,除非使用SecurityManager,并避免在运行时对实例进行任何反射有害的更改,否则可以使用反射来完成此操作。
- 有一件事我没有意识到——实际上你不能创建静态的外部类。所以数学不是一个静态类,而是一个带有静态方法的类。现在开始明白了!这个页面有一些很好的额外信息(可能或多或少是Luiggi在StackOverflow页面上试图让我了解的内容);ttp://www.geeksforgeks.org/static-class-in-java/
- 只需注意,该问题有16个答案,不要只阅读已接受的答案。
不,静态内部类是不需要封闭类型的实例的类,当在方法或字段的上下文中使用时,它与静态类不同。对于一个内部类来说,静态本质上使它们成为一个顶级类。当您声明一个非静态的内部类时,它具有对封闭类型的实例字段和方法的隐式访问权,从而使所述类型的实例成为一个需求。静态类没有这种奢华,因此不需要封闭类型的实例。
- 但是我们显然不能在没有实例化的情况下使用LinkedStack?所以,在这里拥有静态节点不是没有意义吗?
- 所以当嵌套在linkedstack中时,static class Node意味着您可以拥有许多节点对象?但是,当static class Node不嵌套在linkedstack中时,意味着只有一个节点?
静态内部类与外部类(在本例中为LinkedStack)关联,而不是与外部类的实例关联。对于非静态的内部类,应该有一个外部类的封闭实例。如果Node不是静态的,这意味着对于Node的任何实例来说,必须有一个LinkedStack实例包围该实例。
将Node类作为静态类使它更像是一个顶级类,不绑定到外部类的实例。因此,其他类可以创建Node的实例,而不创建LinkedStack的任何实例。
从Java教程中查看嵌套类,以了解更多的差异。
- 好吧,你的答案和Mark W的答案非常相似。我的想法是,Eckel的代码在某种意义上是不好的,因为它不希望为这个类定义节点,然后在其他任何地方打开它们以供任何使用。也许他这么做只是因为这对于一个教科书的例子来说更容易?如果节点被设计成可以在LinkedStack之外生成的东西,那么将它们设置为LinkedStack的内部类似乎很奇怪。不管怎样,这是我目前的想法。
- @托普赛尔的埃多克斯1〔2〕阶级一开始甚至不是一个内部阶级。根据定义,内部类是非静态嵌套类。您可以将LinkedStack看作是为Node提供名称空间。它只是一个嵌套在LinkedStack内部的顶级类。
- 谢谢。我最后的结论(不一定是正确的)是这里没有静态嵌套类的特殊原因。它无论如何都是私有的,因此不能在LinkedStack类之外创建节点。因此,嵌套静态类不做(非静态)内部类也做的任何事情。另外,(非静态)内部类可以访问外部类的泛型类型参数(T),并且不需要静态嵌套类必须使用的额外泛型化。