Java中的静态嵌套类,为什么?
我正在查看 LinkedList
的 Java 代码,注意到它使用了静态嵌套类 Entry
。
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
使用静态嵌套类而不是普通内部类的原因是什么?
我能想到的唯一原因是 Entry 无法访问实例变量,因此从 OOP 的角度来看它具有更好的封装性。
但我认为可能还有其他原因,也许是性能。 可能是什么?
笔记。 我希望我的术语是正确的,我会把它称为静态内部类,但我认为这是错误的: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
I was looking at the Java code for LinkedList
and noticed that it made use of a static nested class, Entry
.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
What is the reason for using a static nested class, rather than an normal inner class?
The only reason I could think of, was that Entry doesn't have access to instance variables, so from an OOP point of view it has better encapsulation.
But I thought there might be other reasons, maybe performance. What might it be?
Note. I hope I have got my terms correct, I would have called it a static inner class, but I think this is wrong: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
您链接到的 Sun 页面两者之间有一些关键区别:
不需要
LinkedList.Entry
成为顶级类,因为它仅由LinkedList
使用(还有一些其他接口也具有名为Entry
的静态嵌套类,例如作为Map.Entry
- 相同的概念)。 由于它不需要访问 LinkedList 的成员,因此将其设置为静态是有意义的 - 这是一种更简洁的方法。正如 Jon Skeet 指出的,我认为如果您使用嵌套类,那么从它开始是一个更好的主意是静态的,然后根据您的使用情况决定是否真的需要非静态。
The Sun page you link to has some key differences between the two:
There is no need for
LinkedList.Entry
to be top-level class as it is only used byLinkedList
(there are some other interfaces that also have static nested classes namedEntry
, such asMap.Entry
- same concept). And since it does not need access to LinkedList's members, it makes sense for it to be static - it's a much cleaner approach.As Jon Skeet points out, I think it is a better idea if you are using a nested class is to start off with it being static, and then decide if it really needs to be non-static based on your usage.
在我看来,每当你看到内部类时,问题应该是相反的 - 它真的是否需要成为一个内部类,具有额外的复杂性和隐式的(而不是显式的和更清晰的) ,IMO)对包含类的实例的引用?
请注意,作为 C# 粉丝,我有偏见 - C# 没有等效的内部类,尽管它确实有嵌套类型。 我还不能说我错过了内部课程:)
To my mind, the question ought to be the other way round whenever you see an inner class - does it really need to be an inner class, with the extra complexity and the implicit (rather than explicit and clearer, IMO) reference to an instance of the containing class?
Mind you, I'm biased as a C# fan - C# doesn't have the equivalent of inner classes, although it does have nested types. I can't say I've missed inner classes yet :)
这里需要考虑一些不明显的内存保留问题。 由于非静态内部类维护对其“外部”类的隐式引用,因此如果内部类的实例被强引用,则外部实例也会被强引用。 当外部类没有被垃圾回收时,这可能会导致一些令人头疼的问题,即使看起来没有任何东西引用它。
There are non-obvious memory retention issues to take into account here. Since a non-static inner class maintains an implicit reference to it's 'outer' class, if an instance of the inner class is strongly referenced, then the outer instance is strongly referenced too. This can lead to some head-scratching when the outer class is not garbage collected, even though it appears that nothing references it.
静态内部类用于构建器模式。 静态内部类可以实例化它的外部类,该外部类只有私有构造函数。 您不能对内部类执行相同的操作,因为您需要在访问内部类之前创建外部类的对象。
这将输出 x: 1
Static inner class is used in the builder pattern. Static inner class can instantiate it's outer class which has only private constructor. You can not do the same with the inner class as you need to have object of the outer class created prior to accessing the inner class.
This will output x: 1
静态嵌套类就像任何其他外部类一样,因为它无法访问外部类成员。
只是为了打包方便,我们可以将静态嵌套类合并到一个外部类中以提高可读性。 除此之外,静态嵌套类没有其他用例。
这种用法的示例,您可以在 Android R.java(资源)文件中找到。
android的Res文件夹包含布局(包含屏幕设计)、drawable文件夹(包含项目使用的图像)、values文件夹(包含字符串常量)等。
正弦所有文件夹都是Res文件夹的一部分,android工具生成一个R. java(资源)文件,其内部包含每个内部文件夹的许多静态嵌套类。
这是在 android 中生成的 R.java 文件的外观:
在这里他们只是为了包装方便而使用。
static nested class is just like any other outer class, as it doesn't have access to outer class members.
Just for packaging convenience we can club static nested classes into one outer class for readability purpose. Other than this there is no other use case of static nested class.
Example for such kind of usage, you can find in Android R.java (resources) file.
Res folder of android contains layouts (containing screen designs), drawable folder (containing images used for project), values folder (which contains string constants), etc..
Sine all the folders are part of Res folder, android tool generates a R.java (resources) file which internally contains lot of static nested classes for each of their inner folders.
Here is the look and feel of R.java file generated in android:
Here they are using only for packaging convenience.
嗯,一方面,非静态内部类有一个额外的隐藏字段,指向外部类的实例。 因此,如果 Entry 类不是静态的,那么除了具有不需要的访问权限之外,它还会携带四个指针而不是三个。
一般来说,我想说,如果您定义的类基本上充当数据成员的集合,例如 C 中的“结构”,请考虑将其设为静态。
Well, for one thing, non-static inner classes have an extra, hidden field that points to the instance of the outer class. So if the Entry class weren't static, then besides having access that it doesn't need, it would carry around four pointers instead of three.
As a rule, I would say, if you define a class that's basically there to act as a collection of data members, like a "struct" in C, consider making it static.
来自 http://docs.oracle.com/javase/tutorial/java/ javaOO/whentouse.html:
From http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html:
简单的例子:
如果是非静态的,则类不能被实例化,除非在上层类的实例中(所以不在 main 是静态函数的示例中)
Simple example :
If non-static the class cannot be instantiated exept in an instance of the upper class (so not in the example where main is a static function)
静态与正常的原因之一与类加载有关。 您不能在其父类的构造函数中实例化内部类。
PS:我一直认为“嵌套”和“内部”是可以互换的。 这些术语可能存在细微差别,但大多数 Java 开发人员都会理解。
One of the reasons for static vs. normal have to do with classloading. You cannot instantiate an inner class in the constructor of it's parent.
PS: I've always understood 'nested' and 'inner' to be interchangeable. There may be subtle nuances in the terms but most Java developers would understand either.
JVM 不知道嵌套类。 嵌套只是语法糖。
下图显示了 Java 文件:
下图显示了 java 文件的类文件表示:
请注意,生成了 2 个类文件,一个用于父类,另一个用于嵌套类。
非静态嵌套类的对象可以访问封闭范围。 通过在嵌套对象中保存封闭范围对象的隐式引用来维护对封闭范围的访问
嵌套类是表示嵌套类类型表示父类组件的意图的一种方式。
私有静态嵌套类表示 Point#3 和 Point#3 事实上,嵌套类型只能是父类的子组件。 不能单独使用。
更多详细信息此处< /a>.
JVM knows no nested classes. Nesting is just syntactic sugar.
Below images shows Java file:
Below images show class files representation of the java file :
Notice that 2 class files are generated, one for parent and another for nested class.
Non-static nested class' objects have access to the enclosing scope. That access to the enclosing scope is maintained by holding an implicit reference of the enclosing scope object in the nested object
Nested class is a way to represent the intent that the nested class type represents a component of the parent class.
private static nested class represents Point#3 & the fact the nested type can only be the subcomponent to the parent class. It can't be used separately.
More details here.
非静态内部类可能会导致内存泄漏,而静态内部类可以防止内存泄漏。 如果外部类保存大量数据,则可能会降低应用程序的性能。
Non static inner classes can result in memory leaks while static inner class will protect against them. If the outer class holds considerable data, it can lower the performance of the application.
我不知道性能差异,但正如您所说,静态嵌套类不是封闭类实例的一部分。 创建静态嵌套类似乎更简单,除非您确实需要它作为内部类。
这有点像为什么我总是在 Java 中将变量设置为最终变量 - 如果它们不是最终变量,我知道它们会发生一些有趣的事情。 如果您使用内部类而不是静态嵌套类,应该有一个很好的理由。
I don't know about performance difference, but as you say, static nested class is not a part of an instance of the enclosing class. Seems just simpler to create a static nested class unless you really need it to be an inner class.
It's a bit like why I always make my variables final in Java - if they're not final, I know there's something funny going on with them. If you use an inner class instead of a static nested class, there should be a good reason.
在某些情况下,使用静态嵌套类而不是非静态嵌套类可能会节省空间。 例如:在类中实现一个
Comparator
,比如Student。然后,
static
确保 Student 类只有一个 Comparator,而不是每次创建新的 Student 实例时都实例化一个新的 Comparator。Using a static nested class rather than non-static one may save spaces in some cases. For example: implementing a
Comparator
inside a class, say Student.Then the
static
ensures that the Student class has only one Comparator, rather than instantiate a new one every time a new student instance is created.内部类的优点——
没有外部类的存在内部类将不存在。
内部类有四种类型。
要点 ---
为了在外部类的静态区域调用普通内部类。
外部 0=new 外部();
Outer.Inner i= O.new Inner();
为了在外部类的实例区调用普通内部类。
Inner i=new Inner();
为了在外部类之外调用正常的内部类。
外部 0=new 外部();
Outer.Inner i= O.new Inner();
inside Inner class 这个指向内部类的指针。
this.member-当前内部类
externalclassname.this--外部类
对于内部类适用的修饰符是 --public,default,
final,abstract,strictfp,+private,protected,static
outer$inner 是内部类名。
内部类在实例方法中,我们可以访问外部类的静态和实例字段。
10.内部类中有静态方法,那么我们只能访问
外部类的静态字段。
Adavantage of inner class--
Without existing of outer class inner class will not exist.
There are four types of inner class.
point ---
inorder to invoke normal inner class in static area of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inorder to invoke normal inner class in instance area of outer class.
Inner i=new Inner();
inorder to invoke normal inner class in outside of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inside Inner class This pointer to inner class.
this.member-current inner class
outerclassname.this--outer class
for inner class applicable modifier is -- public,default,
final,abstract,strictfp,+private,protected,static
outer$inner is the name of inner class name.
inner class inside instance method then we can acess static and instance field of outer class.
10.inner class inside static method then we can access only static field of
outer class.