代码之家  ›  专栏  ›  技术社区  ›  Jeremy Edwards

为什么Android更喜欢静态类

  •  37
  • Jeremy Edwards  · 技术社区  · 14 年前

    我看到很多java代码,android喜欢让开发人员使用静态内部类。尤其是像 ViewHolder Pattern

    5 回复  |  直到 14 年前
        1
  •  72
  •   gustafc    14 年前

    非静态内部类始终保持对封闭对象的隐式引用。如果你不需要那个引用,它所做的就是消耗内存。考虑一下:

    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(){}
    }
    
        2
  •  26
  •   Jere.Jones    14 年前

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

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

        3
  •  15
  •   Viliam    14 年前

    static )与“普通”类非常相似,只是不会污染包的名称空间。这是他们(唯一)的区别和好处,我相信这就是你在Android中看到它的原因。

        4
  •  7
  •   josefx    14 年前

    非静态内部类实例持有对外部类实例的引用,而静态内部类实例不持有。

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

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

    它也与它的使用有关,对外部类的引用是内部类的一个ctor参数,要创建一个新的非静态内部类对象,您必须像调用外部类实例上的memberfunction或从外部类的memberfunction中调用ctor。这意味着如果没有外部类的实例,就不能有内部类的实例。

    Outer.Inner in = new Outer().new Inner();
    
        5
  •  5
  •   shoren    14 年前

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

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

    在像swing或android这样的UI类实现中,您将看到静态的内部类,因为它们被视为私有函数。这些类不是为了在外部类之外的可重用性而开发的,它们与外部类的内部实现紧密相连。没有理由公开它们,也没有理由确保它们能够在比外部类需求的特定上下文更多的情况下工作。