1. 程式人生 > >四種內部類,(Inner Class)

四種內部類,(Inner Class)

內部類: 定義在內部的類,不一定非得是定義在類的內部, 可以分為4種類型。
第一: 靜態內部類(定義在類中)

  1. 靜態的內部類與其外部類是編譯成 兩個.class檔案 的,注意的是外部類是不可以定義為靜態的。
    為什麼外部的類不可以定義為靜態的
    解釋:靜態類是沒有實際意義的,而且執行初始化還要佔用大量記憶體,而且假如有靜態類,不能被重寫,不能建立物件,沒啥實際意義。
    備註:其實只需要定義靜態變數、靜態方法、靜態內部類等完全可以滿足需求的。
  2. 只能訪問外部類的靜態成員變數與靜態方法,
    為什麼靜態的只能訪問靜態的?
    解釋: 靜態的變數或者方法是在類被載入的時候被構造的,而非靜態的則是在生成物件的時候建立的,當在靜態裡面呼叫非靜態的時候,可能非靜態的還沒有沒建立,會發生非法訪問。所以靜態的只能訪問靜態的。

  3. 生成靜態內部類物件的方式為:
    OuterClass.InnerClass inner = new OuterClass.InnerClass();

// B是A的靜態內部類
public  class A{
    public static class B{
    }
}

第二: 成員內部類(內部的非靜態的類)(定義在類中)
1. 可以訪問外部類的靜態與非靜態的方法與成員變數。
2. 生成成員內部類物件的方式為: (和靜態內部類是不同的)
OuterClass.InnerClass inner = new OuterClass().new InnerClass();

為啥這樣寫:
因為是非靜態的類,可以類比成非靜態的一個成員方法,必須通過一個例項化的物件來呼叫,而靜態的內部類可以直接通過類名來呼叫,所以靜態的內部類可以直接通過 外部類名.內部類名 呼叫 ; 而成員內部類必須通過 new 外部類().內部類() 呼叫。 通過外部類的一個物件來呼叫內部類

  1. 也是生成兩個.class 檔案
  2. 若想在區域性內部類中訪問外部類的成員變數,語法 OuterClass.this.a;
// B是A的成員內部類, 與靜態內部類的區別是有無static關鍵字
public class A{
    private  int  a;
    public
class B{ private int a; public void set(){ a= A.this.a; // 內部類中 使用 OuterClass.this.a; 訪問外部的成員 } } }

第三: 區域性內部類(定義在方法中的)用的比較少

類似於一個區域性變數,不能定義成 public private,protected 訪問修飾符的變數, 原因是區域性變數前面不能帶有訪問修飾符,訪問修飾符只能修飾成員變數。

我們是沒有辦法在外部類中使用的,只能在其所定義的成員方法內使用

區域性內部類中是不能訪問外部類的成員或者方法的,只能訪問方法中宣告的 final型別的變數

第四: 匿名內部類 (Anonymous inner class )

內部類,但是沒有名字 沒有名字就意味著沒有構造方法, 是一種特殊的區域性內部類。

匿名內部類會隱式地繼承一個父類或實現一個介面。最重要的特點

//  一個測試類
public class AnonymousInnerClass {
    @SuppressWarnings("deprecation")
    public String getTime(Date  date){
        return date.toLocaleString();
    }

    public static void main(String[] args) {
        AnonymousInnerClass  annoymousClass  =  new AnonymousInnerClass();
        // 傳給 getTime方法中的物件是一個Date類的物件
        String  str = annoymousClass.getTime(new Date());

        // 在這裡new Date(){  } 就是定義了一個內部類,
        // 這個內部類繼承了 Date 這個類,但是沒有重寫 Date類中的任何方法
        //  然後傳給 getTime方法中的物件是一個繼承了Date類的子類的物件
        // 可以看生成的.class 檔案,會多了一個,而且內部類因為沒有名字,所以就 $num  以數字的方式表示了內部類
        String  strInner = annoymousClass.getTime(new Date(){  } );
        System.out.println(str);
        System.out.println(strInner);       

    }
}

通常也是用在方法內的,一般作為引數傳遞進去

Swing 使用匿名內部類實現了監聽介面,為一個事件新增一個監聽器,適用於 該內部類實現的功能只會被使用一次,或者被一個物件使用的情況,不必要再為其單獨的寫一個類。

public  static  void  main (){
    JFrame  frame  =  new JFrame("JFrame");
    JButton  button  = new JButton("click me");
    // 使用內部匿名類的形式為button添加了一個監聽器,
    // 有人可能有疑問ActionListener不是一個介面嗎?怎麼還可以new 出來一個物件,這是內部匿名類的機制,這個地方建立的物件是一個實現了ActionListener介面的具體的例項的物件,並不是一個ActionListener介面物件。
    button.addActionListener (new  ActionListener(){
            public  void  actionPerformed(ActionEvent e){
                   System.out.println("welcome");
            }
     })
}