1、內部類訪問特點:
- 內部類可以直接訪問外部類的成員,包括私有。
- 外部類要訪問內部類的成員,必須創建對象。
- 外部類名.內部類名 對象名 = 外部類對象.內部類對象;
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //外部類名.內部類名 = 外部類對象.內部類對象 4 Outer.Inner oi = new Outer().new Inner(); //創建內部類對象 5 oi.method(); 6 7 } 8 } 9 10 class Outer { 11 private int num = 10; 12 class Inner { 13 public void method() { 14 System.out.println(num); 15 } 16 } 17 }
2、私有成員內部類
- 通過本類中提供一個公共的方法來訪問私有成員內部類。
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //Outer.Inner oi = new Outer().new Inner(); 4 //oi.method(); //這種方法不可以訪問,因為成員內部類已經私有了 5 6 Outer o = new Outer(); 7 o.print(); 8 } 9 } 10 11 class Outer { 12 private int num = 10; 13 private class Inner { 14 public void method() { 15 System.out.println(num); 16 } 17 } 18 19 //本類中提供一個公共的訪問方式,通過本類中的方法訪問私有成員內部類 20 public void print() { 21 Inner i = new Inner(); 22 i.method(); 23 } 24 }
3、靜態成員內部類
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //外部類名.內部類名 對象名 = 外部類名.內部類對象; 4 //其實這句話中new的位置是在Inner()前,new是修飾Inner()的:Outer.new Inner(); 5 //但是一般將new提到最前面,否則編譯會報錯,所以就寫成下面這樣了 6 Outer.Inner oi = new Outer.Inner(); 7 oi.method(); 8 //內部類里面靜態方法的訪問特點:外部類.內部類.靜態方法名(); 9 Outer.Inner2.print(); 10 } 11 } 12 13 class Outer { 14 static class Inner { 15 public void method() { 16 System.out.println("method"); 17 } 18 } 19 20 static class Inner2 { 21 public static void print() { 22 System.out.println("print"); 23 } 24 } 25 }
4、局部內部類訪問局部變量
- 局部內部類訪問局部變量,該局部變量必須用final修飾
- 局部內部類在訪問他所在方法中的局部變量必須用final修飾,為什么?
* 因為當調用這個方法時,局部變量如果沒有用final修飾,他的生命周期和方法的生命周期是一樣的,當方法彈棧,這個局部變量也會消失,那么如果局部內部類對象還沒有馬上消失想用這個局部變量,就沒有了。如果用final修飾會在類加載的時候進入常量池,即使方法彈棧,常量池的常量還在,也可以繼續使用。
* 但是jdk 1.8取消了這個事情,所以我認為這是個bug。
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 Outer o = new Outer(); 4 //o.run(); //錯誤,因為Inner在method方法中,屬於局部成員。方法外無法訪問 5 o.method(); 6 } 7 } 8 9 class Outer { 10 public void method() { 11 //int num = 10; //錯誤: 從內部類中訪問本地變量num; 需要被聲明為最終類型 12 final int num=10; 13 class Inner { 14 public void print() { 15 System.out.println(num); 16 } 17 } 18 19 Inner i = new Inner(); 20 i.print(); 21 } 22 23 /*public void run() { 24 Inner i = new Inner(); //局部內部類,只能在其所在的方法中訪問 25 i.print(); 26 }*/ 27 }
5、面試題
- 例:
1 class Test { 2 public static void main(String[] args) { 3 Outer.Inner oi = new Outer().new Inner(); 4 oi.show(); 5 } 6 } 7 //要求:使用已知的變量,在控制台輸出30,20,10。 8 //內部類之所以能獲取到外部類的成員,是因為他能獲取到外部類的引用。外部類名.this 9 class Outer { 10 public int num = 10; 11 class Inner { 12 public int num = 20; 13 public void show() { 14 int num = 30; 15 System.out.println(num); 16 System.out.println(this.num); 17 //System.out.println(new Outer().num); //使用對象來訪問成員變量 18 System.out.println(Outer.this.num); 19 } 20 } 21 }
6、個人總結:
- 普通內部類可通過在別的類中直接實例化訪問,或者將該內部類的實例化寫在該內部類所在的類中的一個方法里,外部通過調用該方法訪問內部類。
- 私有成員內部類是將內部類的實例化放在了該內部類所在的類中的一個方法里,該方法提供了一個可供外部公共訪問的方式,外部可通過該方法訪問私有成員內部類。
- 靜態成員內部類與普通內部類相似,可在別的類中直接(實例化)訪問或在該內部類所在的類中寫一個方法用來(實例化)訪問該內部類。只不過靜態成員內部類可通過類名調用來訪問。
- 局部內部類是將該內部類的實例化直接寫在了該內部類所在的方法體中,因為它相當於一個局部變量,在方法體外是訪問不到的。