四種內部類,(Inner Class)
內部類: 定義在內部的類,不一定非得是定義在類的內部, 可以分為4種類型。
第一: 靜態內部類(定義在類中)
- 靜態的內部類與其外部類是編譯成 兩個.class檔案 的,注意的是外部類是不可以定義為靜態的。
為什麼外部的類不可以定義為靜態的
解釋:靜態類是沒有實際意義的,而且執行初始化還要佔用大量記憶體,而且假如有靜態類,不能被重寫,不能建立物件,沒啥實際意義。
備註:其實只需要定義靜態變數、靜態方法、靜態內部類等完全可以滿足需求的。 只能訪問外部類的靜態成員變數與靜態方法,
為什麼靜態的只能訪問靜態的?
解釋: 靜態的變數或者方法是在類被載入的時候被構造的,而非靜態的則是在生成物件的時候建立的,當在靜態裡面呼叫非靜態的時候,可能非靜態的還沒有沒建立,會發生非法訪問。所以靜態的只能訪問靜態的。生成靜態內部類物件的方式為:
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 外部類().內部類() 呼叫。 通過外部類的一個物件來呼叫內部類
- 也是生成兩個.class 檔案
- 若想在區域性內部類中訪問外部類的成員變數,語法 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");
}
})
}