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