为什么Android更喜欢静态类

时间:2010-06-24 02:42:30

标签: java android performance static-classes

我看到很多java代码,其中android更喜欢让开发人员使用静态内部类。特别是对于自定义ListAdapters中的ViewHolder Pattern等模式。

我不确定静态类和非静态类之间的区别。我已经读过它但是在关注性能或内存占用时似乎没有意义。

5 个答案:

答案 0 :(得分:67)

这不仅仅是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(){}
}

答案 1 :(得分:25)

静态和非静态内部类之间的主要区别在于,非静态内部类可以访问外部类的其他成员,即使它们是私有的。非静态内部类是外部类的“部分”。如果没有外部类的实例,您就无法创建也无法存在。这样做的结果是,当外部类的实例被销毁时,会破坏非静态内部类的实例。

另一方面,静态内部类就像普通的外部类一样。生死攸关。您不需要外部类的实例来存在内部类。这意味着他们也有自己的生命周期。当垃圾收集器决定销毁它们时,它们就会被销毁。

这对内存和/或性能有何影响?我真的不知道。 :)

答案 2 :(得分:15)

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

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

答案 3 :(得分:6)

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

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

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

它的使用也是相关的,对外部类的引用是内部类的ctor参数,要创建一个新的非静态内部类对象,你必须像外部实例上的成员函数一样调用ctor类或来自外部类的成员函数。这意味着如果没有外部类的实例,就不能拥有内部类的实例。

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

答案 4 :(得分:5)

如果您反编译内部类(或使用调试器观察它),您可以看到生成的代码用于访问用于创建它们的外部类的实例。这样的开销是额外指针的更多内存,因为额外的测试指针,垃圾收集的cpu更多,如果你想选择更长的编译时间。创建非静态内部类的实例有点复杂,因为您需要外部类的实例来创建它们。

可以控制静态和非静态内部类的可见性。通常它们是私有的,如果它们的实现与外部类的内部细节强烈连接,并且开发人员不认为代码可以被重用。从这个意义上说,他们并不比私人职能更好。在类似Map.Entry的情况下,内部类可能是公共的,其中内部类强烈地连接到类所公开的接口,并且开发人员不认为Map.Entry可以在没有某种Map的情况下使用。两种类型都可以访问外部类的私有成员,外部类可以访问内部类的私有成员。

静态和非静态内部类的实例像其他所有类一样被垃圾收集。外部类的grabage集合和内部类的垃圾收集之间没有特殊的连接。

对于像swing或android这样的UI类实现,你会看到静态内部类,因为它们被视为私有函数。这些类不是为了在外部类之外的可重用性而开发的,并且与外部类的内部实现紧密相关。没有理由公开它们并确保它们可以在更多情况下工作,而不是外部类要求的特定上下文。