一、位置
成員內部類是最普通的內部類,它定義在一個類的內部
二、內部類的結構
1.可以定義非靜態屬性和方法,不可以定義static修飾的屬性和方法,可以定義static final修飾的編譯期變量【不用加載類的字節碼】
1.1為什么不可以定義static修飾的屬性和方法?
首先內部類是外部類的一個成員,只有當外部類初始化的時候,內部類才能初始化,靜態變量屬於類級別,在類加載的時候就初始化,
所以兩者本身在語法上就有矛盾。
1.2為什么可以定義static final修飾的變量?
首先要先知道sttaic final修飾的變量叫做常量,常量分為編譯期常量和非編譯期常量
編譯期常量:在程序編譯階段【不需要加載類的字節碼】,就可以確定常量的值
非編譯期常量:在程序運行階段【需要加載類的字節碼】,可以確定常量的值
public class OutterClass { class Inner{ int a = 0;//非靜態變量 static int b = 0;//靜態變量【報錯!!】 static final int c = 0;//編譯期常量,不需要類加載 static final Integer d = new Integer(2);//非編譯期常量,需要類加載【報錯!!】 } public static void main(String[] args) { System.out.println(OutterClass.Inner.b); System.out.println(OutterClass.Inner.c); System.out.println(OutterClass.Inner.d); } }
b屬性是靜態的,它需要加載類的字節碼Inner類,由於它是在OutterClass內部,需要外部類實例化才能加載,但是調用處沒有實例化外部類,所以Inner也不會類加載,所以報錯!!
c屬性是編譯期常量,它不需要加載類的字節碼Inner類,所以不會報錯
d屬性是非編譯期常量。它需要加載類的字節碼Inner類,所以報錯!!
2.內部類可以被任何訪問修飾符修飾
因為它也是類的成員
三、內部類訪問外部類
1.可以訪問任何屬性和方法【包括私有的、靜態的】
訪問方式有2種 :直接寫屬性名或者是外部類.this.屬性【方法】
1.1直接寫屬性名
這種方式有個缺點:如果內部類定義的屬性【方法】和外部類一樣,會發生隱藏現象,取得的是內部類的值,若想取得外部類的值,采用外部類.this.屬性【方法】
1.2若采用直接寫屬性名獲得外部類值,其實本質還是外部類.this.屬性
源碼:
public class Outter { private int a = 3; class Inner{ public void get(){ System.out.println(a); } } }
反編譯后的源碼:Outter.class【編譯成產生了2個字節碼文件Outter.class和Outter$Inner.class】
public class Outter { private int a; public Outter() { this.a = 3; } class Inner { public void get() { System.out.println(Outter.this.a); } } }
四、外部類訪問內部類
1.訪問普通屬性和方法
class Outter { class Inner{ int a = 3; public void get(){ System.out.println("hello"); } } public static void main(String[] args) { Outter.Inner in = new Outter().new Inner(); System.out.println(in.a); in.get(); } }
2.訪問常量
class Outter { class Inner{ static final int a = 4; } public static void main(String[] args) { //第一種 Outter.Inner in = new Outter().new Inner(); System.out.println(in.a); //第二種 System.out.println(Outter.Inner.a); } }
以上是我對成員內部類的總結,如果有不對的地方還請指出,大家共同進步!!