内部类:Android与Java

时间:2012-04-11 18:56:01

标签: java android

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

谢谢!

2 个答案:

答案 0 :(得分: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的生命周期之外的对象,你应该没问题。但它确实可能通过内部阶级泄露您的活动。

答案 1 :(得分: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