07_JavaSE之OOP--面向對象(內部類)
對象(七)
一、內部類(inner class)的概述
內部類,顧名思義就是定義在一個類中的一個類。如:
1 class OuterClass{ 2 3 class InnerClass{ 4 5 } 6 }
接下來,我們就來談談為什麽要使用內部類,以及他有什麽特點,如何使用等等。
1.為什麽要使用內部類呢?
- 內部類方法可以訪問該類定義所在的作用域數據,包括私有數據。
- 內部類可以對同一個包中的其他類隱藏起來。
- 當你想定義一個回調函數不想編寫大量代碼是,使用匿名內部類比較便捷。[1]
2.內部類訪問特點以及如何使用
- 使用原因其實也就是其特點之一:可以訪問該類定義所在的作用域數據,包括私有數據
- 外部類訪問內部類成員,則必須要創建對象。
見代碼:
1 public class Test_InnerClass { 2 public static void main(String[] args){ 3 //外部類名.內部類名 對象名 = 外部類對象.內部類對象; 4 OuterClass.InnerClass oi = new OuterClass().new InnerClass(); 5 //調用方法 6 oi.method(); 7 } 8 } 9 10 class OuterClass{11 private int num = 10; 12 class InnerClass{ 13 public void method(){ 14 System.out.println(num); //可以直接訪問外部類的成員變量 15 System.out.println("感謝關註~"); 16 } 17 } 18 }
結果:
二、成員內部類私有(private) & 靜態成員內部類(static)
1.成員內部類私有
所謂成員內部類私有也就是把內部類加個private,變成私有的。如:
1 class OuterClass{ 2 private class InnerClass{ 3 public void method(){ 4 System.out.println("感謝關註~"); 5 } 6 } 7 }
InnerClass前面加個private關鍵字,沒錯,就是這樣。
那麽如何使用呢?
talk is cheap,show me the code.來:
1 class OuterClass{
2
3 private class InnerClass{//成員內部類被私有了
4 public void method(){
5 System.out.println("感謝關註~");
6 }
7 }
8
9 //通過在外部類當中寫一個方法實例化內部類,調用其方法
10 public void invokeMethod(){
11 InnerClass innerClass = new InnerClass();
12 innerClass.method();
13 }
14
15 }
如果想要調用,那麽就在通過在外部類當中寫一個方法實例化內部類,調用其方法。
2.靜態成員內部類
靜態成員內部類,在內部類加static。如:
1 public class Test_InnerClass { 2 public static void main(String[] args){ 3 //外部類名.內部類名 對象名 = 外部類名.內部類對象; 4 OuterClass.InnerClass o = new OuterClass.InnerClass(); 5 o.method(); 6 } 7 } 8 9 class OuterClass{ 10 static class InnerClass{ 11 public void method(){ 12 System.out.println("Hello World"); 13 } 14 } 15 }
結果:
可見,通過外部類名.內部類名 對象名 = 外部類名.內部類對象,進行調用。
可能到這裏,有一點會產生混淆。就是單純內部類調用時和靜態內部類調用時。
因此做個比較:
普通內部類調用 |
外部類名.內部類名 對象名 = 外部類對象.內部類對象
|
靜態內部類調用 |
外部類名.內部類名 對象名 = 外部類名.內部類對象 OuterClass.InnerClass o = new OuterClass.InnerClass();
|
普通內部類以及靜態內部類,了解即可。哈哈
接下來看看這個題目:(要求控制臺輸出 30,20,10)
1 class Outer { 2 public int num = 10; 3 class Inner { 4 public int num = 20; 5 public void show() { 6 int num = 30; 7 System.out.println(A); 8 System.out.println(B); 9 System.out.println(C); 10 } 11 } 12 } 13 class TestInnerClass{ 14 public static void main(String[] args) { 15 Outer.Inner oi = new Outer().new Inner(); 16 oi.show(); 17 } 18 }
A B C如何填呢?
內部類之所以能獲取到外部類的成員,是因為他能獲取到外部類的引用。外部類.this,進而獲取到他的值。
三、局部內部類(方法裏面的內部類)
所謂局部內部類,其實就是方法裏面的內部類。如:
1 public class Test_InnerClass { 2 public static void main(String[] args) { 3 OuterClass outerClass = new OuterClass(); 4 outerClass.method(); 5 } 6 } 7 8 class OuterClass { 9 10 public void method() { 11 class InnerClass { //局部內部類 12 13 public void playChiJi(){ 14 System.out.println("大吉大利,今晚吃雞~"); 15 } 16 } 17 //只能在方法裏進行實例化並訪問吃雞方法 18 InnerClass innerClass = new InnerClass(); 19 innerClass.playChiJi(); 20 } 21 22 /* 23 這種方法行不通,因為作用域的問題,內部類只存在於方法內,因此在外部類裏實例化不了InnerClass 24 public void invoke(){ 25 InnerClass innerClass = new InnerClass(); 26 innerClass.playChiJi(); 27 } 28 */ 29 }
結果:
那局部內部類訪問局部變量呢?
1 public class Test_InnerClass { 2 public static void main(String[] args) { 3 OuterClass outerClass = new OuterClass(); 4 outerClass.method(); 5 } 6 } 7 8 class OuterClass { 9 public void method() { 10 final int num = 10; 11 class InnerClass { //局部內部類 12 13 public void playChiJi(){ 14 System.out.println(num);//局部內部類訪問局部成員方法 15 } 16 } 17 //只能在方法裏進行實例化並訪問吃雞方法 18 InnerClass innerClass = new InnerClass(); 19 innerClass.playChiJi(); 20 } 21 22 }
結果:輸出10.
在jdk1.8之前,局部變量前面必須加final修飾,因為當調用這個方法時,局部變量如果沒有用final修飾,他的生命周期和方法的生命周期是一樣的,當方法彈棧,這個局部變量也會消失,那麽如果局部內部類對象還沒有馬上消失想用這個局部變量,就沒有了,如果用final修飾會在類加載的時候進入常量池,即使方法彈棧,常量池的常量還在,也可以繼續使用。簡而言之,就是加了final就延長了局部變量的生命周期,方法彈棧可以繼續訪問。
但是,jdk1.8以後可以不加final。其實是默認替你添加上了。
四、匿名內部類(沒有名字的類?)
對,其實就是沒有名字的類。哈哈。
實際上是對內部類的一種簡寫,適合哪種只調用一次方法的情形。
(非匿名內部類)
1 public class Test_InnerClass { 2 public static void main(String[] args) { 3 OuterClass outerClass = new OuterClass(); 4 outerClass.method(); 5 } 6 } 7 8 //定義一個接口 9 interface NoNameInter { 10 void playLOL(); 11 } 12 13 class OuterClass { 14 15 class InnerClass implements NoNameInter { 16 //重寫方法 17 @Override 18 public void playLOL() { 19 System.out.println("晚上一起開黑~"); 20 } 21 } 22 23 //這個是有名字的內部類 24 public void method(){ 25 InnerClass innerClass = new InnerClass(); 26 innerClass.playLOL();; 27 } 28 }View Code
(匿名內部類)
1 public class Test_InnerClass { 2 public static void main(String[] args) { 3 OuterClass outerClass = new OuterClass(); 4 outerClass.method(); 5 } 6 } 7 8 //定義一個接口 9 interface NoNameInter { 10 void playLOL(); 11 } 12 13 class OuterClass { 14 15 public void method(){ 16 17 new NoNameInter(){//匿名內部類 18 //重寫方法 19 @Override 20 public void playLOL() { 21 System.out.println("晚上一起開黑~"); 22 } 23 }.playLOL(); 24 } 25 26 }View Code
咱們得一個一個進行解釋,首先匿名內部類書寫的格式是:
new 類名或者接口名(){
重寫方法;
}
前提:存在一個類或者接口
這裏的類可以是具體類也可以是抽象類,正如代碼中的按個NoNameInter接口。
他的本質是繼承了該類或者實現了該類接口的子類匿名對象。我去,好繞口。就是,
這就是匿名內部類的書寫方式,以及用法。
如有錯誤之處,歡迎指正。
07_JavaSE之OOP--面向對象(內部類)