把一個類放在另一個類內部定義,即爲內部類。
一、非靜態內部類
二、靜態內部類
三、局部內部類
四、匿名內部類
其中前面兩個是類成員,我們可以稱作爲成員內部類,既然作爲成員,那麼就像成員變量一樣,可以使用private、protected、public、默認、static這樣的修飾符。
-----------------------------------------------------------------------------------------------------------------
接下來我們依次進行討論:
- 非靜態內部類:
- 可以訪問外部類的成員變量,不用管是private還是啥的,外部類的一切都可以訪問;外部類不可以直接使用非靜態內部類的成員,如果要使用則必須顯示創建非靜態內部類對象來訪問,可以看3。
原因:非靜態內部類對象裏,保存了一個他所寄生的外部類對象的引用。
2. 對於外部類成員變量、非靜態內部類成員變量、非靜態內部類方法的局部變量同名的情況
外部類名字.this.成員變量名 this.成員變量名 局部變量名
public class Outer{
private String prop="外部prop";
private class Inner{
private String prop="內部prop";
public void info(){
String prop="方法prop";
System.out.println(prop);
System.out.println(this.prop);
System.out.println(Outer.this.prop);
}
}
}
3. 不允許在外部類的靜態成員中直接使用非靜態內部類
class Outer{
class Inner{
private int prop=5;
//private static int x;//錯誤的,不允許在非靜態內部類定義任何靜態的東西
}
public void test1(){
System.out.println(new Inner().prop);
}
public static void test2(){
//System.out.println(new Inner().prop);//錯誤的,不允許在外部類的靜態成員中直接使用非靜態內部類
}
}
4. 編譯會生成兩個文件:Outer.class Outer$Inner.class5. 非靜態內部類必須寄生在外部類對象裏,而外部類對象則不必一定有非靜態內部類對象寄生其中。這也就解釋了爲什麼外部類對象不可以訪問非靜態內部類成員,因爲可能非靜態內部類對象根本就不存在。
- 靜態內部類:屬於外部類本身,而不是外部類的某個對象
1. 只能訪問外部類的靜態成員(類成員),而不能訪問實例變量
2. 靜態內部類不是寄生在外部類對象,而是寄生在外部類的類本身當中。當靜態內部類對象存在的時候,不一定存在一個被他寄生的外部類對象,他只有外部類的引用,沒有外部類對象的引用。
3. 外部類仍然不可以直接訪問內部類的成員。如果要使用則必須顯示創建非靜態內部類對象來訪問(針對實例成員) 或者 使用內部類的類名來訪問(針對靜態成員)。
總結一句話:
靜態內部類裏面可以定義靜態的和非靜態的成員變量、方法...,可以隨意訪問外部類的靜態的一切
非靜態內部類只能定義非靜態的成員變量、方法...,可以隨意訪問外部類的一切
外部類訪問靜態內部類,對於靜態的,用類名.XXX, 對於非靜態的,用new 內部類名().XXX
外部類訪問非靜態內部類,因爲非靜態內部類根本沒有非靜態的東東了,當然就是用new 內部類名().XXX
-----------------------------------------------------------------------------------------------------------------
在外部類的外面使用內部類:
非靜態內部類: 外部類名.內部類名 變量名=new 外部類名().new 內部類名();
靜態內部類: 外部類名.內部類名 變量名=new 外部類名.內部類名();
補充:如果一個類繼承了非靜態內部類,那麼必須讓子類構造器可以調用父類構造器,調用非靜態內部類的構造器的時候,必須存在一個外部類對象。
比如:
public class SubClass extends Out.In{
public SubClass(Out out){
out.super();//調用父類的構造器,父類是Out類的非靜態內部類
}
}
創建非靜態內部類In對象和他的子類都應該持有Out對象的引用,只是他們傳入的方式不同:
當創建非靜態內部類In類的對象的時候,必須通過Out對象來調用new關鍵字;
當創建SubClass類的對象時,必須使用Out對象作爲調用者來調用In類的構造器。
-----------------------------------------------------------------------------------------------------------------
- 局部內部類:在方法裏定義,不能使用static修飾
外部類的名字$N局部內部類的名字.class
- 匿名內部類:匿名內部類不能是抽象類;不能定義構造器,但匿名內部類可以定義初始化塊
被匿名內部類訪問的局部變量,可以用final修飾,也可以不用final修飾,但必須按照有final修飾的方式來用。也就是一次賦值之後,以後不可以再次重新賦值。