为什么Android更喜欢静态类

我看到很多的Java代码,Android喜欢让开发人员使用静态内部类。 特别适用于像自定义ListAdapters中的ViewHolder Pattern那样的模式 。

我不确定静态类和非静态类之间有什么区别。 我已经读过了,但是在关注性能或者内存占用方面似乎没有意义。

这不仅仅是Android开发者…

非静态的内部类总是保持对封闭对象的隐式引用。 如果你不需要这个参考,它所做的只是成本记忆。 考虑一下:

class Outer { class NonStaticInner {} static class StaticInner {} public List<Object> foo(){ return Arrays.asList( new NonStaticInner(), new StaticInner()); } } 

当你编译它时,你会得到如下的结果:

 class Outer { Outer(){} public List<Object> foo(){ return Arrays.asList( new Outer$NonStaticInner(this), new StaticInner()); } } class Outer$NonStaticInner { private final Outer this$0; Outer$NonStaticInner(Outer enclosing) { this$0 = enclosing; } } class Outer$StaticInner { Outer$StaticInner(){} } 

静态内部类和非静态内部类之间的主要区别在于非静态内部类可以访问外部类的其他成员,即使它们是私有的也是如此。 非静态的内部类是外部类的“部分”。 没有外部类的实例,你不能创build,也不能创build它们。 这样做的结果是当外部类的实例被销毁时,非静态内部类的实例被销毁。

另一方面,静态内部类就像正常的外部类。 活着,自己死去。 您不需要内部类的外部类的实例存在。 这意味着他们也有自己的生命周期。 当垃圾收集者决定销毁它们时,它们被毁坏。

这如何影响内存和/或性能? 我真的不知道。 🙂

静态内部类(即在关键字static另一个类中声明的类)与“普通”类非常相似,除非不污染包的名称空间。 这是他们(唯一的)区别和好处,我相信这就是你在Android中看到它的原因。

当类的目的是紧缩到主类时使用静态内部类,但不依赖于它的实例。 这通常被认为是一个好的做法。

如果你反编译一个内部类(或者使用debugging器来观察),你可以看到生成的代码用于访问用于创build它们的外部类的实例。 这个额外的指针的更多内存的开销,更多的CPU垃圾收集,因为额外的指针testing,如果你想挑选,更长的编译时间。 创build非静态内部类的实例有点复杂,因为你需要一个外部类的实例来创build它们。

静态和非静态内部类的可见性可以被控制。 通常情况下,它们是私有的,如果它们的实现与外部类的内部细节紧密相连,开发人员不认为代码可以被重用。 在这个意义上,他们并不比私人function好。 在Map.Entry这样的情况下,内部类可能是公开的,在这种情况下,内部类与类所公开的接口强有力地连接,开发人员不认为Map.Entry可以在没有某种Map的情况下使用。 两种types都可以访问外部类的私有成员,而外部类可以访问内部类的私有成员。

静态和非静态内部类的实例像其他类一样被垃圾收集。 外部类的垃圾收集与内部类的垃圾收集之间没有特别的联系。

在UI类实现像swing或android的情况下,您将看到静态内部类,因为它们被视为私有函数。 这些类不是为外部类之外的可重用性开发的,而是与外部类的内部实现紧密相连的。 没有理由暴露他们,并确保他们可以在比外部要求的具体情况更多的情况下工作。

非静态的内部类实例拥有对外部类实例的引用,而静态的内部类实例不包含该静态内部类实例。

这与应用程序内存占用相关,因为隐藏引用可能导致内存泄漏 – 垃圾收集器无法收集外部类实例,直到没有更多引用存在。 另外附加的引用本身需要内存,如果使用大量的实例,这可能是相关的。

 class Outer{ class Inner{//Only works with non static inner class public Outer getOuter(){return Outer.this;} } } 

它也与它的使用相关,对外部类的引用是内部类的一个参数,创build一个新的非静态内部类对象,你必须像外部类的实例上的成员函数那样调用Ctor,或者在外部成员职能之内。 这意味着,如果没有外部类的实例,则不能拥有内部类的实例。

 Outer.Inner in = new Outer().new Inner();