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