c2c電子商務(wù)網(wǎng)站建設(shè)欄目結(jié)構(gòu)圖最近國際新聞
文章目錄
- 一、內(nèi)部類的概念
- 二、內(nèi)部類的分析
- 三、內(nèi)部類的分類
- 1. 成員內(nèi)部類
- 2. 靜態(tài)內(nèi)部類
- 3. 局部內(nèi)部類
- 4. 匿名內(nèi)部類
- 匿名內(nèi)部類與Lambda表達(dá)式
一、內(nèi)部類的概念
在 Java 中,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類。內(nèi)部類的出現(xiàn),再次打破了Java單繼承的局限性。
內(nèi)部類一般分為4種:成員內(nèi)部類、靜態(tài)內(nèi)部類、局部內(nèi)部類和匿名內(nèi)部類。
注意:內(nèi)部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩個類。
二、內(nèi)部類的分析
-
內(nèi)部類的位置
- 成員內(nèi)部類:定義在外部類的內(nèi)部,類似于成員方法,類和成員都不能使用static修飾
- 靜態(tài)內(nèi)部類:定義在外部類的內(nèi)部,類似于靜態(tài)方法,類使用static修飾,成員也可使用static修飾
- 局部內(nèi)部類:定義在外部類的某一作用域內(nèi)部(如靜態(tài)代碼塊、代碼塊、靜態(tài)方法、普通方法),類和成員都不能使用static修飾
- 匿名內(nèi)部類:定義在外部類的任意位置(如靜態(tài)變量、成員變量、靜態(tài)代碼塊、代碼塊、靜態(tài)方法、普通方法),類和成員都不能使用static修飾
-
內(nèi)部類與外部類的依賴
- 成員內(nèi)部類:依賴外部類,需要通過外部類對象來創(chuàng)建成員內(nèi)部類的實例對象
- 靜態(tài)內(nèi)部類:不依賴外部類,可直接創(chuàng)建靜態(tài)內(nèi)部類的實例對象
- 局部內(nèi)部類:與外部類無關(guān),只能在該局部位置內(nèi)創(chuàng)建局部內(nèi)部類對象
- 匿名內(nèi)部類:與外部類無關(guān)
-
內(nèi)部類可以擁有的成員
- 成員內(nèi)部類:可擁有非靜態(tài)的成員,可使用任何修飾符修飾
- 靜態(tài)內(nèi)部類:可擁有任何的成員(靜態(tài)、非靜態(tài)),可使用任何修飾符修飾
- 局部內(nèi)部類:可擁有非靜態(tài)的成員,可使用任何修飾符修飾
- 匿名內(nèi)部類:可擁有非靜態(tài)的成員,可使用任何修飾符修飾
-
內(nèi)部類訪問外部類成員
- 成員內(nèi)部類:可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
- 靜態(tài)內(nèi)部類:可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的
- 局部內(nèi)部類:
- 若定義在靜態(tài)部分中,可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的;
- 若定義在非靜態(tài)部分中,可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
- 匿名內(nèi)部類:
- 若定義在靜態(tài)部分中,可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的;
- 若定義在非靜態(tài)部分中,可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
-
外部類訪問內(nèi)部類成員
- 成員內(nèi)部類:外部類想要訪問成員內(nèi)部類的成員,需要先創(chuàng)建成員內(nèi)部類實例對象,再通過實例對象去訪問。
- 靜態(tài)內(nèi)部類:
- 外部類可訪問靜態(tài)內(nèi)部類的靜態(tài)成員,可以是任何修飾符修飾的;
- 外部類想要訪問靜態(tài)內(nèi)部類的非靜態(tài)成員,需要先創(chuàng)建靜態(tài)內(nèi)部類實例對象,再通過實例對象去訪問。
- 局部內(nèi)部類:外部類不可訪問局部內(nèi)部類成員
- 匿名內(nèi)部類:外部類想要訪問匿名內(nèi)部類的成員,需要能拿到匿名內(nèi)部類實例對象,再通過實例對象去訪問(但也只能訪問當(dāng)匿名內(nèi)部類的父類原有成員,若是匿名內(nèi)部類自定義的成員則還是無法訪問)。
-
內(nèi)部類成員和外部類成員重名
內(nèi)部類使用成員時,當(dāng)外部類的成員和內(nèi)部類的成員重名時,會發(fā)生隱藏現(xiàn)象(外部類的成員會被隱藏),默認(rèn)情況下訪問的是內(nèi)部類的成員(就近原則),所以一般建議:
- 在內(nèi)部類中訪問自己的靜態(tài)成員:<內(nèi)部類>.<內(nèi)部類中的成員名>
- 在內(nèi)部類中訪問自己的非靜態(tài)成員:this.<內(nèi)部類中的成員名>
- 在內(nèi)部類中訪問外部類的靜態(tài)成員:<外部類類名>.<外部類中的成員名>
- 在內(nèi)部類中訪問外部類的非靜態(tài)成員:<外部類類名>.this.<外部類中的成員名>
-
內(nèi)部類和外部類的編譯
外部類和內(nèi)部類在編譯后是兩個不同的class文件。
- 成員內(nèi)部類:內(nèi)部類的class文件名稱:外部類名$內(nèi)部類名.class
- 靜態(tài)內(nèi)部類:內(nèi)部類的class文件名稱:外部類名$內(nèi)部類名.class
- 局部內(nèi)部類:內(nèi)部類的class文件名稱:外部類名$編號+內(nèi)部類名.class
- 匿名內(nèi)部類:內(nèi)部類的class文件名稱:外部類名$編號.class
三、內(nèi)部類的分類
內(nèi)部類可分為四種:
- 成員內(nèi)部類
- 靜態(tài)內(nèi)部類
- 局部內(nèi)部類
- 匿名內(nèi)部類
1. 成員內(nèi)部類
成員內(nèi)部類是最普通的內(nèi)部類,它的定義為位于另一個類的內(nèi)部。類似于成員方法,成員內(nèi)部類不能擁有靜態(tài)域但是可以訪問外部類的靜態(tài)部分。
- 定義在外部類的內(nèi)部,類似于成員方法,類和成員都不能使用static修飾
- 依賴外部類,需要通過外部類對象來創(chuàng)建成員內(nèi)部類的實例對象
- 可擁有非靜態(tài)的成員,可使用任何修飾符修飾
- 可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
- 外部類想要訪問成員內(nèi)部類的成員,需要先創(chuàng)建成員內(nèi)部類實例對象,再通過實例對象去訪問
- 內(nèi)部類使用成員時,當(dāng)外部類的成員和內(nèi)部類的成員重名時,會發(fā)生隱藏現(xiàn)象(外部類的成員會被隱藏),默認(rèn)情況下訪問的是內(nèi)部類的成員(就近原則)
- 外部類和內(nèi)部類在編譯后是兩個不同的class文件,內(nèi)部類的class文件名稱:外部類名$內(nèi)部類名.class
public class OuterClass {private static String a = "outer static filed";private String b = "outer filed";public static String method1() {return "outer static method";}public String method2() {return "outer method";}class InnerClass {public void getOuter() {// 1.成員內(nèi)部類訪問外部類的靜態(tài)變量System.out.println(OuterClass.a);// 2.成員內(nèi)部類訪問外部類的靜態(tài)方法System.out.println(OuterClass.method1());// 3.成員內(nèi)部類訪問外部類的成員變量System.out.println(OuterClass.this.b);System.out.println(b);// 不建議使用這種方式// 4.成員內(nèi)部類訪問外部類的普通方法System.out.println(OuterClass.this.method2());System.out.println(method2());// 不建議使用這種方式}}
}
public static void main(String[] args) {// 方式1:OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();// 方式2:OuterClass outerClass = new OuterClass();InnerClass innerClass1 = outerClass.createInnerClass();}
創(chuàng)建成員內(nèi)部類實例
格式:外部類名.內(nèi)部類名 成員內(nèi)部類對象名 = new 外部類名().new 內(nèi)部類名()
2. 靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類也是定義在另一個類里面的類,使用static修飾,類似于靜態(tài)方法,靜態(tài)內(nèi)部類不需要外部類對象產(chǎn)生就能使用,靜態(tài)內(nèi)部類只能訪問外部類的靜態(tài)部分,不能訪問外部類的實例部分。
- 定義在外部類的內(nèi)部,類似于靜態(tài)方法,類使用static修飾,成員也可使用static修飾
- 不依賴外部類,可直接創(chuàng)建靜態(tài)內(nèi)部類的實例對象
- 可擁有任何的成員(靜態(tài)、非靜態(tài)),可使用任何修飾符修飾
- 可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的
- 外部類可訪問靜態(tài)內(nèi)部類的靜態(tài)成員,可以是任何修飾符修飾的;
- 外部類想要訪問靜態(tài)內(nèi)部類的非靜態(tài)成員,需要先創(chuàng)建靜態(tài)內(nèi)部類實例對象,再通過實例對象去訪問。
- 內(nèi)部類使用成員時,當(dāng)外部類的成員和內(nèi)部類的成員重名時,會發(fā)生隱藏現(xiàn)象(外部類的成員會被隱藏),默認(rèn)情況下訪問的是內(nèi)部類的成員(就近原則)
- 外部類和內(nèi)部類在編譯后是兩個不同的class文件,內(nèi)部類的class文件名稱:外部類名$內(nèi)部類名.class
public class OuterClass {private static String a = "outer static filed";private String b = "outer filed";public static String method1() {return "outer static method";}public String method2() {System.out.println(b);return "outer method";}static class InnerClass {private static String b = "inner filed";public String method2() {return "outer method";}public void getOuter() {System.out.println(a);}}
}
創(chuàng)建靜態(tài)內(nèi)部類實例
格式:外部類名.內(nèi)部類名 成員內(nèi)部類對象名 = new 外部類名.內(nèi)部類名()
public class Test {public static void main(String[] args) {OuterClass.InnerClass innerClass = new OuterClass.InnerClass();}
}
3. 局部內(nèi)部類
局部內(nèi)部類是定義在一個方法或者一個作用域里面的類,它和成員內(nèi)部類的區(qū)別在于局部內(nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi),類似于局部變量。
- 定義在外部類的某一作用域內(nèi)部(如靜態(tài)代碼塊、代碼塊、靜態(tài)方法、普通方法),類和成員都不能使用static修飾
- 局部內(nèi)部類與外部類無關(guān),只能在該局部位置內(nèi)創(chuàng)建局部內(nèi)部類對象
- 可擁有非靜態(tài)的成員,可使用任何修飾符修飾
- 若定義在靜態(tài)部分中,可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的;
- 若定義在非靜態(tài)部分中,可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
- 外部類不可訪問局部內(nèi)部類成員
- 內(nèi)部類使用成員時,當(dāng)外部類的成員和內(nèi)部類的成員重名時,會發(fā)生隱藏現(xiàn)象(外部類的成員會被隱藏),默認(rèn)情況下訪問的是內(nèi)部類的成員(就近原則)
- 外部類和內(nèi)部類在編譯后是兩個不同的class文件,內(nèi)部類的class文件名稱:外部類名$編號+內(nèi)部類名.class
public class OuterClass {private static String a = "outer static filed";private String b = "outer filed";static {class InnerClass1 {public void method2() {System.out.println(a);}}}{class InnerClass1 {public void method2() {System.out.println(a);System.out.println(b);}}}public static void method1() {class InnerClass1 {public void method2() {System.out.println(a);}}}public void method2() {class InnerClass1 {public void method2() {System.out.println(a);System.out.println(b);}}InnerClass1 innerClass1 = new InnerClass1();}
}
創(chuàng)建局部內(nèi)部類實例
在局部內(nèi)部類的作用域內(nèi)通過new對象的方式創(chuàng)建對象。
格式:局部內(nèi)部類名 局部內(nèi)部類對象名 = 局部內(nèi)部類名();
4. 匿名內(nèi)部類
匿名內(nèi)部類應(yīng)該是我們編寫代碼時用得最多的,它滿足了我們動態(tài)自定義代碼的需求。
匿名內(nèi)部類可以看作是特殊的局部內(nèi)部類,其本質(zhì)就是一個繼承/實現(xiàn)了某個類(接口,普通類,抽象類)的子類匿名對象。
- 匿名內(nèi)部類沒有名稱,沒有構(gòu)造函數(shù),且使用者無法創(chuàng)建構(gòu)造函數(shù),但是實際上JDK為匿名內(nèi)部類生成了構(gòu)造函數(shù)
- 定義在外部類的任意位置(如靜態(tài)變量、成員變量、靜態(tài)代碼塊、代碼塊、靜態(tài)方法、普通方法),類和成員都不能使用static修飾
- 匿名內(nèi)部類與外部類無關(guān)
- 可擁有非靜態(tài)的成員,可使用任何修飾符修飾
- 若定義在靜態(tài)部分中,可以訪問外部類靜態(tài)的成員,可以是任何修飾符修飾的;
- 若定義在非靜態(tài)部分中,可以訪問外部類任何的成員(靜態(tài)、非靜態(tài)),可以是任何修飾符修飾的
- 外部類想要訪問匿名內(nèi)部類的成員,需要能拿到匿名內(nèi)部類實例對象,再通過實例對象去訪問(但也只能訪問當(dāng)匿名內(nèi)部類的父類原有成員,若是匿名內(nèi)部類自定義的成員則還是無法訪問)。
- 外部類和內(nèi)部類在編譯后是兩個不同的class文件,內(nèi)部類的class文件名稱:外部類名$編號.class
匿名內(nèi)部類的定義
格式:new 接口名|類名(){重寫方法}
如果重寫方法為非必要的,原則上是可以沒有重寫方法部分的。
public class Test {public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {}};Runnable runnable1 = new Runnable() {@Overridepublic void run() {}};}
}
匿名內(nèi)部類與Lambda表達(dá)式
從Java8開始,引入了Lambda表達(dá)式,將代碼塊作為參數(shù)使用更簡潔的代碼來創(chuàng)建只有一個抽象方法的接口(這種接口被稱為函數(shù)式接口)的實例。
Lambda表達(dá)式的代碼塊就是實現(xiàn)接口方法的方法體。
public class Test {public static void main(String[] args) {Runnable runnable = () -> {System.out.println("run.... ");};}
}
Lambda代碼塊寫的是Runnable接口的run方法的方法體。
兩者的不同之處:
- 使用匿名內(nèi)部類方式定義的內(nèi)部類:編譯之后,會生成一個單獨的class字節(jié)碼文件(外部類名$編號.class);
- 使用Lambda表達(dá)式創(chuàng)建的內(nèi)部類:編譯之后,不會生成一個單獨的class字節(jié)碼文件,對應(yīng)的字節(jié)碼會在運行的時候動態(tài)生成。