1. 程式人生 > >07_JavaSE之OOP--面向對象(內部類)

07_JavaSE之OOP--面向對象(內部類)

抽象類 p s pub 接下來 圖片 class 分享 接口的子類匿名對象 void

對象(七)

一、內部類(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 oi = new OuterClass().new InnerClass();
靜態內部類調用

外部類名.內部類名 對象名 = 外部類名.內部類對象

 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接口。

他的本質是繼承了該類或者實現了該類接口的子類匿名對象。我去,好繞口。就是,

技術分享圖片

這就是匿名內部類的書寫方式,以及用法。

如有錯誤之處,歡迎指正。

郵箱:[email protected]

07_JavaSE之OOP--面向對象(內部類)