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) {
//匿名內部類
//可用於對接口的簡單實例化 ,通常只使用一次
}
};