Java 中有多种内部类,其实平时经常用到,这里整理一下,用到比较多都是Android的例子。
1.成员内部类
这是最常见的一种内部类,大部分为了方便而写在一个文件里面的类基本都属于这样的,
优点:使用灵活,不用写太多的文件
缺点:在外部创建内部类实例需要先创建一个Container的实例
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
故比较适合只在当前类里使用的,比如某个自定义的 View
public class OuterLayout extends FrameLayout{
private class InnerLayout extends View {
// 这就是一个成员内部类
public InnerLayout(Context context) {
super(context);
}
}
//省略...
}
2. 静态内部类
OuterClass.InnerClass inner = new OuterClass.InnerClass();
优点:同样是使用方便,和1相比,避免内存泄露
缺点:不能灵活的使用非静态的实例,所在的 OuterClass 的很多类成员属性都不能直接使用。
使用场景:类内部使用的java Bean常用
关于泄露
非静态内部类的对象默认包含了它的Container的引用,比如:
class A{
class B{ }
}
B的对象中默认有一个A的引用,垃圾回收的时候,如果处理不当,有可能导致A的对象不能被回收,导致内存泄漏。
换成静态内部类后,默认引用就没有了,比如:
class A{
static class B{ }
}
泄露栗子:
public class ExampleActivity extends Activity{
private static LeakClass leakInstance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(leakInstance == null) {
leakInstance = new LeakClass();
}
}
private class LeakClass {
//这个内部类创建后就持有了Activity的引用
}
}
leakInstance由于是一个内部类,持有了activity的引用,此时如果activity被销毁重建,那么原先的activity就会被leakInstance持有,不能被回收。
所以建议改成
private static class LeakClass
3. 局部内部类
在方法内部创建的类,生命周期只存在于方法周期内,少用
4. 匿名内部类
优点:使用简单,方便快捷,实现接口的实例比较方便
缺点:使用太多的话会造成代码可读性差
栗子:
OnClickListener l = new OnClickListener() {
@Override
public void onClick(View v) {
//匿名内部类
//可用于对接口的简单实例化 ,通常只使用一次
}
};