7

我知道在 Android 中不建议使用内部类,因为它们包含对封闭类的引用。但是,在 Java 中,只有当不再引用内部类时,才会对外部类进行 GC。这意味着,在 Android 中,如果您在外部活动类中对内部类有一个非静态引用,则内部类不能比外部活动类存在的时间更长,因为活动只有在没有引用的情况下才能被销毁不再是内部类(至少这是我所推断的)。那么使用非静态内部类有什么问题(因为如果你从java推断,它们显然不能比外部活动存在更长的时间)?我错过了什么吗?

谢谢!

4

2 回答 2

8

考虑这个简单的例子

class Leaker 
{
    public static Object leakedObj;
}

class MyActivity extends Activity
{
     public class MyInnerClass { ... }

     void onCreate(Bundle savedState) 
     {
        Leaker.leakedObj = new MyInnerClass();
        //The activity now won't be GCed until Leaker.leakedObj is cleared.          
     }
}

您可以轻松地在活动上下文之外传递内部非静态类。只要您不将内部类传递给 Activity 生命周期之外的对象,就应该没问题。但肯定有可能通过内部类泄露您的活动。

于 2012-04-11T19:04:23.297 回答
6

我不会费心解释,因为谷歌可以更好地解释它。

假设:父类是Foo,内部类是Foo$Inner

问题是 VM 认为从 Foo$Inner 直接访问 Foo 的私有成员是非法的,因为 Foo 和 Foo$Inner 是不同的类,即使 Java 语言允许内部类访问外部类的私有成员。为了弥补差距,编译器生成了几个合成方法:

/*package*/ static int Foo.access$100(Foo foo) {
    return foo.mValue;
}
/*package*/ static void Foo.access$200(Foo foo, int value) {
    foo.doStuff(value);
}

每当需要访问 mValue 字段或调用外部类中的 doStuff 方法时,内部类代码都会调用这些静态方法。这意味着上面的代码实际上归结为您通过访问器方法访问成员字段的情况。之前我们谈到了访问器是如何比直接字段访问慢的,所以这是一个特定的语言习惯用法导致“无形”性能下降的例子。

如果您在性能热点中使用这样的代码,您可以通过将内部类访问的字段和方法声明为具有包访问权限而不是私有访问权限来避免开销。不幸的是,这意味着这些字段可以被同一个包中的其他类直接访问,所以你不应该在公共 API 中使用它。

来源:https ://developer.android.com/training/articles/perf-tips.html#PackageInner

于 2012-04-11T19:04:43.707 回答