深入了解Java內(nèi)部類的用法
1.內(nèi)部類分類和概念
java類的五大成員:屬性,方法,構(gòu)造器(構(gòu)造方法),代碼塊,內(nèi)部類
內(nèi)部類的分類:
定義在外部類局部的位置(比如方法內(nèi)):
- 局部內(nèi)部類(有類名)
- 匿名內(nèi)部類(無類名)
定義在外部類成員位置上:
- 成員內(nèi)部類(沒有static修飾)
- 靜態(tài)內(nèi)部類(有static修飾)
概念:在一個(gè)類的內(nèi)部再定義一個(gè)完整的類,也會生成一個(gè)class文件
代碼示例:
/** * 內(nèi)部類 */ public class InnerClass { private int n = 521; public InnerClass(int n) { this.n = n; } class Inner { // 內(nèi)部類 } }
謹(jǐn)記:內(nèi)部類很重要,java底層源碼內(nèi)部類使用場景很多!
2.局部內(nèi)部類
class Outer001 { // 外部類 private int n = 521; private void kaka() { System.out.println("我是外部類的方法!"); } public void show() { // 局部內(nèi)部類定義在外部類的局部位置,通常在方法中 class Inner001 { // 局部內(nèi)部類 public void f() { // 可以直接訪問外部類的所有成員,包含私有的 System.out.println(n); } } } }
不能添加訪問修飾符,但是可以添加final
局部內(nèi)部類的作用域只在定義它的方法或者代碼塊中
外部類使用內(nèi)部類的方法,直接new即可:
public void show() { // 局部內(nèi)部類定義在外部類的局部位置,通常在方法中 final class Inner001 { // 局部內(nèi)部類 public void f() { // 可以直接訪問外部類的所有成員,包含私有的 System.out.println(n); kaka(); } } // 外部類使用內(nèi)部類的方法 Inner001 inner001 = new Inner001(); inner001.f(); }
外部其他類不能訪問局部內(nèi)部類!
外部類和局部內(nèi)部類的成員重名時(shí),默認(rèn)遵循就近原則,如果想要訪問外部類的成員,使用外部類名.this.成員進(jìn)行訪問
3.匿名內(nèi)部類(重要)
匿名內(nèi)部類其實(shí)有名字,它的名字是底層的JDK給分配的~系統(tǒng)分配該類名的時(shí)候會在外部類的基礎(chǔ)上加上$1,存在多個(gè)內(nèi)部類的,$后面的值進(jìn)行遞增
基于接口的匿名內(nèi)部類
/** * 匿名內(nèi)部類 */ public class AnonymousInnerClass { public static void main(String[] args) { Outer002 outer002 = new Outer002(); outer002.method(); } } class Outer002 { private int n = 521; public void method() { // 基于接口的匿名內(nèi)部類 // tiger的編譯類型是IA,運(yùn)行類型就是匿名內(nèi)部類! // 系統(tǒng)分配該類名的時(shí)候會在外部類的基礎(chǔ)上加上$1,此處是Outer002$1 // JDK底層在創(chuàng)建了匿名內(nèi)部類之后,立即創(chuàng)建了一個(gè)實(shí)例,并且把地址返回給tiger IA tiger = new IA() { @Override public void cry() { System.out.println("我是一只小老虎??"); } }; tiger.cry(); System.out.println(tiger.getClass()); } } interface IA { public void cry(); }
輸出:
我是一只小老虎??
class seniorobject.innerclass.Outer002$1
注意:匿名內(nèi)部類使用一次就不能再使用了!
基于類的匿名內(nèi)部類
基于類的匿名內(nèi)部類和基于接口的差不太多
Father類:
class Father { private String name; public Father(String name) { this.name = name; } public void test() { } }
匿名內(nèi)部類:
// 基于類的匿名內(nèi)部類,加入大括號就搖身一變變成內(nèi)部類了 Father jack = new Father("jack"){ @Override public void test() { super.test(); System.out.println("?(^?^*)"); } }; System.out.println(jack.getClass());
輸出:
class seniorobject.innerclass.Outer002$2
一些細(xì)節(jié)
匿名內(nèi)部類是類,同時(shí),它也可以理解為是一個(gè)對象
匿名內(nèi)部類可以訪問外部類的所有成員,包括私有的
不能添加訪問修飾符
定義域在定義它的方法或者代碼塊中,轉(zhuǎn)瞬即逝!
外部其他類不能訪問匿名內(nèi)部類
外部類和匿名內(nèi)部類成員重名時(shí),參照局部內(nèi)部類的方式即可
匿名內(nèi)部類的最佳實(shí)踐
當(dāng)作實(shí)參直接傳遞,簡潔高效
/** * 匿名內(nèi)部類的最佳實(shí)踐 * 當(dāng)作實(shí)參直接傳遞,簡潔高效 */ public class AnonymousInnerClassPractice { public static void main(String[] args) { f(new IL() { @Override public void show() { System.out.println("你好啊"); } }); } public static void f(IL il) { il.show(); } } interface IL { void show(); }
4.成員內(nèi)部類
定義在外部類的成員位置上:
實(shí)例:
/** * 成員內(nèi)部類 */ public class MemberInnerClass { public static void main(String[] args) { Outer003 outer003 = new Outer003(); outer003.t(); } } class Outer003 { private int n = 521; public String name = "dahe"; class Inner003 { // 成員內(nèi)部類 public void say() { System.out.println(n + name); } } public void t() { // 使用成員內(nèi)部類 Inner003 inner003 = new Inner003(); inner003.say(); } }
輸出:
521dahe
可以訪問外部類的所有成員,包括私有的
可以添加任意的訪問修飾符
作用域?yàn)檎麄€(gè)類體中
外部類想要使用成員內(nèi)部類,創(chuàng)建對象調(diào)用即可!
外部其他類想要訪問成員內(nèi)部類,存在兩種方式:
// 直接創(chuàng)建對象 Outer003.Inner003 inner003 = outer003.new Inner003(); // 注意:這里的outer003是外部類的對象實(shí)例
// 成員內(nèi)部類的外部類創(chuàng)建一個(gè)返回內(nèi)部類對象的公有方法 public Inner003 getInner003Instance() { return new Inner003(); } // 外部其他類進(jìn)行調(diào)用該共有方法 Outer003.Inner003 inner0031 = outer003.getInner003Instance(); inner0031.say();
外部類和成員內(nèi)部類的成員重名時(shí),參考局部內(nèi)部類和匿名內(nèi)部類即可
5.靜態(tài)內(nèi)部類
可以直接訪問外部類的靜態(tài)成員
可以添加任意的訪問修飾符
作用域?yàn)檎麄€(gè)類體
外部類想要訪問靜態(tài)內(nèi)部類依然是創(chuàng)建對象訪問
外部其他類想要訪問靜態(tài)內(nèi)部類:
// 通過類名直接訪問 Outer004.Inner004 inner004 = new Outer004.Inner004(); inner004.say();
// 靜態(tài)內(nèi)部類的外部類創(chuàng)建一個(gè)返回內(nèi)部類對象的公有方法 // 返回靜態(tài)內(nèi)部類的對象實(shí)例 public Inner004 getInner004() { return new Inner004(); } Outer004.Inner004 inner0041 = outer004.getInner004(); inner0041.say();
// 返回靜態(tài)內(nèi)部類的對象實(shí)例,但是是靜態(tài)方法 public static Inner004 getInner004_() { return new Inner004(); } // 靜態(tài)內(nèi)部類的外部類創(chuàng)建一個(gè)返回內(nèi)部類對象的公有靜態(tài)方法 Outer004.Inner004 inner0042 = Outer004.getInner004_(); inner0042.say();
整體代碼示例:
/** * 靜態(tài)內(nèi)部類 */ public class StaticInnerClass { public static void main(String[] args) { Outer004 outer004 = new Outer004(); // 通過類名直接訪問 Outer004.Inner004 inner004 = new Outer004.Inner004(); inner004.say(); // 靜態(tài)內(nèi)部類的外部類創(chuàng)建一個(gè)返回內(nèi)部類對象的公有方法 Outer004.Inner004 inner0041 = outer004.getInner004(); inner0041.say(); // 靜態(tài)內(nèi)部類的外部類創(chuàng)建一個(gè)返回內(nèi)部類對象的公有靜態(tài)方法 Outer004.Inner004 inner0042 = Outer004.getInner004_(); inner0042.say(); } } class Outer004 { private int n = 521; private static String name = "dahe"; public static class Inner004 { public void say() { // 可以直接訪問外部類的靜態(tài)成員 System.out.println(name); } } // 返回靜態(tài)內(nèi)部類的對象實(shí)例 public Inner004 getInner004() { return new Inner004(); } // 返回靜態(tài)內(nèi)部類的對象實(shí)例,但是是靜態(tài)方法 public static Inner004 getInner004_() { return new Inner004(); } }
外部類和成員內(nèi)部類的成員重名時(shí),遵循就近原則,如果想要訪問外部類的成員,使用外部類名.成員即可
以上就是深入了解Java內(nèi)部類的用法的詳細(xì)內(nèi)容,更多關(guān)于Java內(nèi)部類的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Netty網(wǎng)絡(luò)編程實(shí)戰(zhàn)之開發(fā)聊天室功能
這篇文章主要為大家詳細(xì)介紹了如何利用Netty實(shí)現(xiàn)聊天室功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Netty網(wǎng)絡(luò)編程有一定幫助,需要的可以參考一下2022-10-10看動畫學(xué)算法之Java實(shí)現(xiàn)doublyLinkedList
這篇文章主要介紹Java實(shí)現(xiàn)doublyLinkedList,LinkedList:doublyLinkedList相對比較復(fù)雜,今天就來簡單學(xué)習(xí)一下doublyLinkedList的基本操作和概,感興趣的小伙伴可以參考下面具體文章內(nèi)容2021-10-10Java 數(shù)據(jù)結(jié)構(gòu)之時(shí)間復(fù)雜度與空間復(fù)雜度詳解
算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用: 時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長短;而空間復(fù)雜度是度量算法所需存儲空間的大小2021-11-11Java實(shí)現(xiàn)Huffman編碼的示例代碼
Huffman編碼是一種編碼方式,本文主要介紹了Java實(shí)現(xiàn)Huffman編碼的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08Spring項(xiàng)目中使用Cache?Redis實(shí)現(xiàn)數(shù)據(jù)緩存
這篇文章主要為大家介紹了項(xiàng)目中使用Spring?Cache?Redis實(shí)現(xiàn)數(shù)據(jù)緩存,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06