解析JavaSe的內(nèi)部類
內(nèi)部類
1. 內(nèi)部類簡(jiǎn)介
(1) 內(nèi)部類提供了更好的封裝,可以把內(nèi)部類隱藏在外部類之內(nèi),不允許同一個(gè)包中的其他類訪問該類。
(2) 內(nèi)部類成員可以直接訪問外部類的私有數(shù)據(jù),因?yàn)閮?nèi)部類被當(dāng)成其外部類成員,同一個(gè)類的成員之間可以互相訪問。但外部類不能訪問內(nèi)部類的實(shí)現(xiàn)細(xì)節(jié),例如內(nèi)部類的成員變量。
(3) 匿名內(nèi)部類適合用于創(chuàng)建那些僅需要一次使用的類。
(4) 在java中內(nèi)部類主要分為成員內(nèi)部類(非靜態(tài)內(nèi)部類、靜態(tài)內(nèi)部類)、匿名內(nèi)部類、局部?jī)?nèi)部類。
2. 非靜態(tài)內(nèi)部類
成員內(nèi)部類是一種與Field、方法、構(gòu)造器和初始化塊相似的類成員,成員內(nèi)部類分為兩種:靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類,使用static修飾的成員內(nèi)部類是靜態(tài)內(nèi)部類,沒有使用static修飾的成員內(nèi)部類是非靜態(tài)內(nèi)部類。
- 因?yàn)閮?nèi)部類作為其外部類的成員,所以可以使用任意訪問控制符如private、protected和public等修飾;
- 非靜態(tài)內(nèi)部類不能有靜態(tài)方法、靜態(tài)屬性、靜態(tài)初始化塊;
- 非靜態(tài)內(nèi)部類可以直接訪問外部類的成員,但是外部類不能直接訪問非靜態(tài)內(nèi)部類成員;
- 外部類的靜態(tài)方法、靜態(tài)代碼塊中不能直接創(chuàng)建非靜態(tài)內(nèi)部類實(shí)例,訪問內(nèi)部類成員;
- 非靜態(tài)內(nèi)部類的對(duì)象必須寄存在外部類的對(duì)象里,因此創(chuàng)建非靜態(tài)內(nèi)部類對(duì)象之前,必須先創(chuàng)建其外部類對(duì)象;
當(dāng)在非靜態(tài)內(nèi)部類的方法內(nèi)訪問某個(gè)變量時(shí),系統(tǒng)優(yōu)先在該方法內(nèi)查找是否存在該名字的局部變量,如果存在就使用該變量;如果不存在,則到該方法所在的內(nèi)部類中查找是否存在該名字的成員變量,如果存在則使用該成員變量;如果不存在,則到該內(nèi)部類所在的外部類中查找是否存在該名字的成員變量,如果存在則使用該成員變量;如果依然不存在,系統(tǒng)將出現(xiàn)編譯錯(cuò)誤:提示找不到該變量。
(1) 非靜態(tài)內(nèi)部類可以直接訪問外部類的成員,但是外部類不能直接訪問非靜態(tài)內(nèi)部類成員
public class OuterClass { private int a; public void test(){ // 編譯報(bào)錯(cuò),因?yàn)橥獠款惒荒苤苯釉L問非靜態(tài)內(nèi)部類成員 System.out.println(b); // 如需訪問內(nèi)部類的實(shí)例Field,需顯式創(chuàng)建內(nèi)部類對(duì)象 InnerClass inner = new InnerClass(); System.out.println(inner.b); } // 定義非靜態(tài)內(nèi)部類,使用private修飾符 @Data private class InnerClass{ private int b; public void info(){ // 在非靜態(tài)內(nèi)部類里可以直接訪問外部類的private成員 System.out.println(a); } } }
(2) 非靜態(tài)內(nèi)部類不能有靜態(tài)方法、靜態(tài)屬性、靜態(tài)初始化塊
public class OuterClass { // 外部類Field private int a; // 定義非靜態(tài)內(nèi)部類,使用private修飾符 @Data private class InnerClass{ // 內(nèi)部類Field private int b; private int c; // 編譯報(bào)錯(cuò),非靜態(tài)內(nèi)部類里面不能有靜態(tài)屬性 private static int d; // 編譯報(bào)錯(cuò),非靜態(tài)內(nèi)部類里面不能有靜態(tài)代碼塊 static { System.out.println("非靜態(tài)內(nèi)部類里面不能有靜態(tài)代碼塊"); } // 編譯報(bào)錯(cuò),非靜態(tài)內(nèi)部類里面不能有靜態(tài)方法 public static void show(){ System.out.println("非靜態(tài)內(nèi)部類里面不能有靜態(tài)方法"); } } }
(3) 外部類的靜態(tài)方法、靜態(tài)代碼塊中不能直接創(chuàng)建非靜態(tài)內(nèi)部類實(shí)例,訪問內(nèi)部類成員
public class OuterClass { private int a; public static void test(){ // 編譯報(bào)錯(cuò),外部類的靜態(tài)方法中無法創(chuàng)建內(nèi)部類實(shí)例 InnerClass innerClass = new InnerClass(); } static{ // 編譯報(bào)錯(cuò),外部類的靜態(tài)方法中無法創(chuàng)建內(nèi)部類實(shí)例 InnerClass innerClass = new InnerClass(); } // 定義非靜態(tài)內(nèi)部類 @Data private class InnerClass{ private int b; } }
在外部類的普通方法和靜態(tài)方法中訪問內(nèi)部類成員
public class OuterClass { private int a; // 定義非靜態(tài)內(nèi)部類,使用private修飾符 @Data private class InnerClass{ private int b; public void info(){ System.out.println("內(nèi)部類的方法info()"); } } // 外部類的代碼塊 { InnerClass innerClass = new InnerClass(); innerClass.info(); } // 外部類的靜態(tài)代碼塊 static { OuterClass.InnerClass inner = new OuterClass().new InnerClass(); inner.info(); } // 外部類的普通方法 public void test(){ // 在外部類里使用非靜態(tài)內(nèi)部類時(shí),與平時(shí)使用普通類并沒有太大的區(qū)別 InnerClass inner = new InnerClass(); // 訪問內(nèi)部類的Filed System.out.println(inner.b); // 訪問內(nèi)部類的方法 inner.info(); } // 外部類的靜態(tài)方法 public static void test1(){ // 外部類的靜態(tài)方法、靜態(tài)代碼塊中不能直接創(chuàng)建非靜態(tài)內(nèi)部類實(shí)例 OuterClass.InnerClass inner = new OuterClass().new InnerClass(); // 訪問內(nèi)部類的Filed System.out.println(inner.b); // 訪問內(nèi)部類的方法 inner.info(); } // 測(cè)試 public static void main(String[] args) { OuterClass outerClass = new OuterClass(); outerClass.test(); } }
3. 靜態(tài)內(nèi)部類
如果使用static來修飾一個(gè)內(nèi)部類,則這個(gè)內(nèi)部類就屬于外部類本身,而不屬于外部類的某個(gè)對(duì)象。static關(guān)鍵字的作用是把類的成員變成類相關(guān),而不是實(shí)例相關(guān),即static修飾的成員屬于整個(gè)類,而不屬于單個(gè)對(duì)象。
- 靜態(tài)內(nèi)部類可以包含靜態(tài)成員,也可以包含非靜態(tài)成員。
- 靜態(tài)內(nèi)部類不能訪問外部類的實(shí)例成員,只能訪問外部類的類成員;
- 外部類不能直接訪問靜態(tài)內(nèi)部類的成員,但可以使用靜態(tài)內(nèi)部類的類名作為調(diào)用者來訪問靜態(tài)內(nèi)部類的類成員,也可以使用靜態(tài)內(nèi)部類對(duì)象作為調(diào)用者來訪問靜態(tài)內(nèi)部類的實(shí)例成員。
(1) 靜態(tài)內(nèi)部類不能訪問外部類的實(shí)例成員,只能訪問外部類的類成員
public class OuterClass { private int a; private static int b; public void test(){ System.out.println(a); } @Data private static class InnerClass{ private int c; // 靜態(tài)內(nèi)部類中可以包括靜態(tài)成員 private static int d; public void info(){ // 編譯報(bào)錯(cuò),靜態(tài)內(nèi)部類不能訪問外部類的實(shí)例成員 System.out.println(a); } public static void show(){ // 靜態(tài)內(nèi)部類可以訪問外部類的靜態(tài)成員 System.out.println(b); } } }
(2) 外部類不能直接訪問靜態(tài)內(nèi)部類的成員,但可以使用靜態(tài)內(nèi)部類的類名作為調(diào)用者來訪問靜態(tài)內(nèi)部類的類成員,也可以使用靜態(tài)內(nèi)部類對(duì)象作為調(diào)用者來訪問靜態(tài)內(nèi)部類的實(shí)例成員。
public class OuterClass { private int a; private static int b; public void test(){ // 外部類不能直接訪問靜態(tài)內(nèi)部類的成員 // 可以使用靜態(tài)內(nèi)部類對(duì)象作為調(diào)用者來訪問靜態(tài)內(nèi)部類的實(shí)例成員 InnerClass innerClass = new InnerClass(); innerClass.show(); // 可以使用靜態(tài)內(nèi)部類的類名作為調(diào)用者來訪問靜態(tài)內(nèi)部類的類成員 InnerClass.show(); } public static void main(String[] args) { OuterClass outerClass = new OuterClass(); outerClass.test(); } @Data private static class InnerClass{ private int c; private static int d; public static void show(){ System.out.println(b); } } }
4. 匿名內(nèi)部類
匿名內(nèi)部類適合創(chuàng)建那種只需要一次使用的類,創(chuàng)建匿名內(nèi)部類時(shí)會(huì)立即創(chuàng)建一個(gè)該類的實(shí)例,這個(gè)類定義立即消失,匿名內(nèi)部類不能重復(fù)使用。
- 匿名內(nèi)部類必須繼承一個(gè)父類,或?qū)崿F(xiàn)一個(gè)接口,但最多只能繼承一個(gè)父類,或?qū)崿F(xiàn)一個(gè)接口;
- 匿名內(nèi)部類不能是抽象類,因?yàn)橄到y(tǒng)在創(chuàng)建匿名內(nèi)部類時(shí),會(huì)立即創(chuàng)建匿名內(nèi)部類的對(duì)象。因此不允許將匿名內(nèi)部類定義成抽象類;
- 匿名內(nèi)部類不能定義構(gòu)造器,因?yàn)槟涿麅?nèi)部類沒有類名,所以無法定義構(gòu)造器,但匿名內(nèi)部類可以定義實(shí)例初始化塊,通過實(shí)例初始化塊來完成構(gòu)造器需要完成的事情;
public interface Product { public int getPrice(); public String getName(); }
public class Test { public void test(Product product){ System.out.println("name:"+product.getName() +"-------"+"name:"+product.getPrice()); } public static void main(String[] args) { Test test = new Test(); test.test(new Product() { @Override public int getPrice() { return 12; } @Override public String getName() { return "蘋果"; } }); } }
Test類定義了一個(gè)test方法,該方法需要一個(gè)Product對(duì)象作為參數(shù),但Product只是一個(gè)接口,無法直接創(chuàng)建對(duì)象,因此此處考慮創(chuàng)建一個(gè)Product接口實(shí)現(xiàn)類的對(duì)象傳入該方法——如果這個(gè)Product接口實(shí)現(xiàn)類需要重復(fù)使用,則應(yīng)該將該實(shí)現(xiàn)類定義成一個(gè)獨(dú)立類;如果這個(gè)Product接口實(shí)現(xiàn)類只需一次使用,則可采用上面程序中的方式,定義一個(gè)匿名內(nèi)部類。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程
這篇文章主要為大家詳細(xì)介紹了Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Java8新特性之再見Permgen_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java8新特性之再見Permgen的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-06-06Mybatis-Plus實(shí)現(xiàn)SQL攔截器的示例
這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)一個(gè)SQL攔截器,通過使用SQL攔截器,開發(fā)人員可以在執(zhí)行SQL語句之前或之后對(duì)其進(jìn)行修改或記錄,從而更好地控制和優(yōu)化數(shù)據(jù)庫(kù)操作,對(duì)Mybatis-Plus?SQL攔截器相關(guān)知識(shí)感興趣的朋友一起看看吧2023-05-05JAVA8 List<List<Integer>> list中再裝一個(gè)list轉(zhuǎn)成一個(gè)list操
這篇文章主要介紹了JAVA8 List<List<Integer>> list中再裝一個(gè)list轉(zhuǎn)成一個(gè)list操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08java中初始化MediaRecorder的實(shí)現(xiàn)方法
這篇文章主要介紹了java中初始化MediaRecorder的實(shí)現(xiàn)方法的相關(guān)資料,希望通過本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10