为什么Android更喜欢静态类
我看到很多java代码中android更喜欢让开发人员使用静态内部类。特别是对于像 ViewHolder 模式。
我不确定静态类和非静态类之间有什么区别。我已经读过它,但当涉及性能或内存占用时,它似乎没有意义。
I see a lot of java code where android prefers to have developers use static inner classes. Particularly for patterns like the ViewHolder Pattern in custom ListAdapters.
I'm not sure what the differences are between static and non-static classes. I've read about it but it doesn't seem to make sense when concerned with performance or memory-footprint.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不仅仅是 Android 开发人员……
非静态内部类始终保留对封闭对象的隐式引用。如果您不需要该引用,它所做的只是消耗内存。考虑一下:
当你编译它时,你得到的将是这样的:
It's not just Android developers...
A non-static inner class always keeps an implicit reference to the enclosing object. If you don't need that reference, all it does is cost memory. Consider this:
When you compile it, what you get will be something like this:
静态内部类和非静态内部类之间的主要区别在于,非静态内部类可以访问外部类的其他成员,即使它们是私有的。非静态内部类是外部类的“一部分”。如果没有外部类的实例,您就无法创建它们,它们也无法存在。这样做的结果是,当外部类的实例被销毁时,非静态内部类的实例也被销毁。
另一方面,静态内部类就像普通的外部类一样。生与死都是自己的。您不需要外部类的实例来使内部类存在。这意味着它们也有自己的生命周期。当垃圾收集器决定销毁它们时,它们就会被销毁。
这如何影响内存和/或性能?我真的不知道。 :)
The main difference between static and non-static inner classes is that a non-static inner class has access to other members of the outer class, even if they are private. Non-static inner classes are a "part" of the outer class. You cannot create nor can they exist without an instance of an outer class. A consequence of this is that an instance of a non-static inner classes are destroyed when the outer class's instance is destroyed.
Static inner classes, on the other hand, are just like normal outer classes. The live and die on their own. You don't need an instance of the outer class for the inner class to exist. That means they also have their own life cycle. They get destroyed when the garbage collector decides to destroy them.
How does this affect memory and/or performance? I really don't know. :)
静态内部类(即在另一个类中使用关键字
static
声明的类)与“普通”类非常相似,只是不会污染包的名称空间。这是它们(唯一的)区别和优点,我相信这就是您在 Android 中看到它的原因。当类的用途与主类紧密相关但不依赖于其实例时,请使用静态内部类。这通常被认为是一个好的做法。
Static inner classes (i.e. classes declared inside another class with keyword
static
) are quite similar to "normal" classes except you don't pollute your package's name space. That is their (only) difference and benefit and I believe that's the reason you see it in Android.Use static inner classes when the purpose of the class is tighten to the main class, but does not depend on its instances. This is generally considered as a good practice.
非静态内部类实例保存对外部类实例的引用,而静态内部类实例则不保存。
这与应用程序内存占用相关,因为隐藏的引用可能会导致内存泄漏 - 垃圾收集器无法收集外部类实例,直到不再存在引用。此外,附加引用本身也需要内存,如果使用大量实例,这可能是相关的。
它也与其使用相关,对外部类的引用是内部类的 ctor 参数,要创建一个新的非静态内部类对象,您必须像外部类实例上的成员函数一样调用该 ctor 或从在外部类的成员函数内。这意味着如果没有外部类的实例,就不能拥有内部类的实例。
A non static inner class instance holds a reference to the outer class instance while a static inner class instance does not.
This is relevant for the applications memory footprint as the hidden reference may lead to memory leaks - the garbage collector cannot collect the outer class instance until no more references exist. Also the additional reference itself needs memory, this may be relevant if a high number of instances are used.
It is also relevant for its use, the reference to the outer class is a ctor argument of the inner class, to create a new non static inner class object you have to call the ctor like a memberfunction on an instance of the outer class or from within a memberfunction of the outer class. This means that you cannot have a instance of the inner class without an instance of the outer class.
如果反编译内部类(或使用调试器观察它),您可以看到生成的代码用于访问用于创建它们的外部类的实例。这样做的开销是更多的内存用于额外的指针,更多的CPU用于垃圾收集,因为需要测试额外的指针,如果你想要nit pick,则需要更长的编译时间。创建非静态内部类的实例有点复杂,因为您需要外部类的实例来创建它们。
静态和非静态内部类的可见性都可以控制。通常,如果它们的实现与外部类的内部细节紧密相关,并且开发人员认为代码无法重用,则它们是私有的。从这个意义上说,它们并不比私有函数更好。在像 Map.Entry 这样的情况下,内部类可能是公共的,其中内部类与类公开的接口强连接,并且开发人员认为没有某种 Map 就不能使用 Map.Entry。两种类型都可以访问外部类的私有成员,并且外部类可以访问内部类的私有成员。
静态和非静态内部类的实例像其他类一样被垃圾收集。外部类的垃圾收集和内部类的垃圾收集之间没有特殊的联系。
对于像 swing 或 android 这样的 UI 类实现,您将看到静态内部类,因为它们被视为私有函数。这些类并不是为了在外部类之外重用而开发的,而是与外部类的内部实现紧密相连。没有理由公开它们并确保它们可以在比外部类要求的特定上下文更多的情况下工作。
If you decompile an inner class (or watch it using debugger) you can see that there is generated code for accessing the instance of the outer class that was used to create them. The overhead for this is more memory for the additional pointer, more cpu for garbage collection because of additional pointer to test, and if you want to nit pick, longer compile time. Creating instances of non static inner classes is a bit more complicated because you need an instance of the outer class to create them.
Visibility of both static and non-static inner classes can be controlled. Usually they are private if their implementation is strongly connnected to internal details of the outer class, and the developer doesn't think the code can be reused. In this sense they are not better than private functions. Inner classes might be public in cases like Map.Entry, where the inner class is strongly connected to the interface exposed by the class, and the developer doesn't think that Map.Entry can be used without some kind of a Map. Both types have access to private members of the outer class and the outer class has access to private members of the inner class.
Instances of static and non-static inner classes are garbage collected like every other class. There is no special connection between the grabage collection of the outer class and the garbage collection of the inner class.
In the case of UI classes implementation like swing or android you will see static inner classes because they are treated like private function. These classes are not developed for reusability outside the outer class and are strongly connected to the internal implementation of the outer class. There is no reason to expose them and to make sure they can work in more cases than the specific context of the outer class requirements.