深入了解Java內(nèi)部類(lèi)的用法
1.內(nèi)部類(lèi)分類(lèi)和概念
java類(lèi)的五大成員:屬性,方法,構(gòu)造器(構(gòu)造方法),代碼塊,內(nèi)部類(lèi)
內(nèi)部類(lèi)的分類(lèi):

定義在外部類(lèi)局部的位置(比如方法內(nèi)):
- 局部?jī)?nèi)部類(lèi)(有類(lèi)名)
- 匿名內(nèi)部類(lèi)(無(wú)類(lèi)名)
定義在外部類(lèi)成員位置上:
- 成員內(nèi)部類(lèi)(沒(méi)有static修飾)
- 靜態(tài)內(nèi)部類(lèi)(有static修飾)
概念:在一個(gè)類(lèi)的內(nèi)部再定義一個(gè)完整的類(lèi),也會(huì)生成一個(gè)class文件

代碼示例:
/**
* 內(nèi)部類(lèi)
*/
public class InnerClass {
private int n = 521;
public InnerClass(int n) {
this.n = n;
}
class Inner { // 內(nèi)部類(lèi)
}
}
謹(jǐn)記:內(nèi)部類(lèi)很重要,java底層源碼內(nèi)部類(lèi)使用場(chǎng)景很多!
2.局部?jī)?nèi)部類(lèi)
class Outer001 { // 外部類(lèi)
private int n = 521;
private void kaka() {
System.out.println("我是外部類(lèi)的方法!");
}
public void show() {
// 局部?jī)?nèi)部類(lèi)定義在外部類(lèi)的局部位置,通常在方法中
class Inner001 {
// 局部?jī)?nèi)部類(lèi)
public void f() {
// 可以直接訪(fǎng)問(wèn)外部類(lèi)的所有成員,包含私有的
System.out.println(n);
}
}
}
}
不能添加訪(fǎng)問(wèn)修飾符,但是可以添加final
局部?jī)?nèi)部類(lèi)的作用域只在定義它的方法或者代碼塊中
外部類(lèi)使用內(nèi)部類(lèi)的方法,直接new即可:
public void show() {
// 局部?jī)?nèi)部類(lèi)定義在外部類(lèi)的局部位置,通常在方法中
final class Inner001 {
// 局部?jī)?nèi)部類(lèi)
public void f() {
// 可以直接訪(fǎng)問(wèn)外部類(lèi)的所有成員,包含私有的
System.out.println(n);
kaka();
}
}
// 外部類(lèi)使用內(nèi)部類(lèi)的方法
Inner001 inner001 = new Inner001();
inner001.f();
}
外部其他類(lèi)不能訪(fǎng)問(wèn)局部?jī)?nèi)部類(lèi)!
外部類(lèi)和局部?jī)?nèi)部類(lèi)的成員重名時(shí),默認(rèn)遵循就近原則,如果想要訪(fǎng)問(wèn)外部類(lèi)的成員,使用外部類(lèi)名.this.成員進(jìn)行訪(fǎng)問(wèn)
3.匿名內(nèi)部類(lèi)(重要)
匿名內(nèi)部類(lèi)其實(shí)有名字,它的名字是底層的JDK給分配的~系統(tǒng)分配該類(lèi)名的時(shí)候會(huì)在外部類(lèi)的基礎(chǔ)上加上$1,存在多個(gè)內(nèi)部類(lèi)的,$后面的值進(jìn)行遞增
基于接口的匿名內(nèi)部類(lèi)
/**
* 匿名內(nèi)部類(lè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)部類(lèi)
// tiger的編譯類(lèi)型是IA,運(yùn)行類(lèi)型就是匿名內(nèi)部類(lèi)!
// 系統(tǒng)分配該類(lèi)名的時(shí)候會(huì)在外部類(lèi)的基礎(chǔ)上加上$1,此處是Outer002$1
// JDK底層在創(chuàng)建了匿名內(nèi)部類(lè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)部類(lèi)使用一次就不能再使用了!
基于類(lèi)的匿名內(nèi)部類(lèi)
基于類(lèi)的匿名內(nèi)部類(lèi)和基于接口的差不太多
Father類(lèi):
class Father {
private String name;
public Father(String name) {
this.name = name;
}
public void test() {
}
}
匿名內(nèi)部類(lèi):
// 基于類(lèi)的匿名內(nèi)部類(lèi),加入大括號(hào)就搖身一變變成內(nèi)部類(lè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)部類(lèi)是類(lèi),同時(shí),它也可以理解為是一個(gè)對(duì)象
匿名內(nèi)部類(lèi)可以訪(fǎng)問(wèn)外部類(lèi)的所有成員,包括私有的
不能添加訪(fǎng)問(wèn)修飾符
定義域在定義它的方法或者代碼塊中,轉(zhuǎn)瞬即逝!
外部其他類(lèi)不能訪(fǎng)問(wèn)匿名內(nèi)部類(lèi)
外部類(lèi)和匿名內(nèi)部類(lèi)成員重名時(shí),參照局部?jī)?nèi)部類(lèi)的方式即可
匿名內(nèi)部類(lèi)的最佳實(shí)踐
當(dāng)作實(shí)參直接傳遞,簡(jiǎn)潔高效
/**
* 匿名內(nèi)部類(lèi)的最佳實(shí)踐
* 當(dāng)作實(shí)參直接傳遞,簡(jiǎn)潔高效
*/
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)部類(lèi)
定義在外部類(lèi)的成員位置上:
實(shí)例:
/**
* 成員內(nèi)部類(lè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)部類(lèi)
public void say() {
System.out.println(n + name);
}
}
public void t() {
// 使用成員內(nèi)部類(lèi)
Inner003 inner003 = new Inner003();
inner003.say();
}
}
輸出:
521dahe
可以訪(fǎng)問(wèn)外部類(lèi)的所有成員,包括私有的
可以添加任意的訪(fǎng)問(wèn)修飾符
作用域?yàn)檎麄€(gè)類(lèi)體中
外部類(lèi)想要使用成員內(nèi)部類(lèi),創(chuàng)建對(duì)象調(diào)用即可!
外部其他類(lèi)想要訪(fǎng)問(wèn)成員內(nèi)部類(lèi),存在兩種方式:
// 直接創(chuàng)建對(duì)象 Outer003.Inner003 inner003 = outer003.new Inner003(); // 注意:這里的outer003是外部類(lèi)的對(duì)象實(shí)例
// 成員內(nèi)部類(lèi)的外部類(lèi)創(chuàng)建一個(gè)返回內(nèi)部類(lèi)對(duì)象的公有方法
public Inner003 getInner003Instance() {
return new Inner003();
}
// 外部其他類(lèi)進(jìn)行調(diào)用該共有方法
Outer003.Inner003 inner0031 = outer003.getInner003Instance();
inner0031.say();
外部類(lèi)和成員內(nèi)部類(lèi)的成員重名時(shí),參考局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi)即可
5.靜態(tài)內(nèi)部類(lèi)
可以直接訪(fǎng)問(wèn)外部類(lèi)的靜態(tài)成員
可以添加任意的訪(fǎng)問(wèn)修飾符
作用域?yàn)檎麄€(gè)類(lèi)體
外部類(lèi)想要訪(fǎng)問(wèn)靜態(tài)內(nèi)部類(lèi)依然是創(chuàng)建對(duì)象訪(fǎng)問(wèn)
外部其他類(lèi)想要訪(fǎng)問(wèn)靜態(tài)內(nèi)部類(lèi):
// 通過(guò)類(lèi)名直接訪(fǎng)問(wèn) Outer004.Inner004 inner004 = new Outer004.Inner004(); inner004.say();
// 靜態(tài)內(nèi)部類(lèi)的外部類(lèi)創(chuàng)建一個(gè)返回內(nèi)部類(lèi)對(duì)象的公有方法
// 返回靜態(tài)內(nèi)部類(lèi)的對(duì)象實(shí)例
public Inner004 getInner004() {
return new Inner004();
}
Outer004.Inner004 inner0041 = outer004.getInner004();
inner0041.say();
// 返回靜態(tài)內(nèi)部類(lèi)的對(duì)象實(shí)例,但是是靜態(tài)方法
public static Inner004 getInner004_() {
return new Inner004();
}
// 靜態(tài)內(nèi)部類(lèi)的外部類(lèi)創(chuàng)建一個(gè)返回內(nèi)部類(lèi)對(duì)象的公有靜態(tài)方法
Outer004.Inner004 inner0042 = Outer004.getInner004_();
inner0042.say();
整體代碼示例:
/**
* 靜態(tài)內(nèi)部類(lèi)
*/
public class StaticInnerClass {
public static void main(String[] args) {
Outer004 outer004 = new Outer004();
// 通過(guò)類(lèi)名直接訪(fǎng)問(wèn)
Outer004.Inner004 inner004 = new Outer004.Inner004();
inner004.say();
// 靜態(tài)內(nèi)部類(lèi)的外部類(lèi)創(chuàng)建一個(gè)返回內(nèi)部類(lèi)對(duì)象的公有方法
Outer004.Inner004 inner0041 = outer004.getInner004();
inner0041.say();
// 靜態(tài)內(nèi)部類(lèi)的外部類(lèi)創(chuàng)建一個(gè)返回內(nèi)部類(lèi)對(duì)象的公有靜態(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() {
// 可以直接訪(fǎng)問(wèn)外部類(lèi)的靜態(tài)成員
System.out.println(name);
}
}
// 返回靜態(tài)內(nèi)部類(lèi)的對(duì)象實(shí)例
public Inner004 getInner004() {
return new Inner004();
}
// 返回靜態(tài)內(nèi)部類(lèi)的對(duì)象實(shí)例,但是是靜態(tài)方法
public static Inner004 getInner004_() {
return new Inner004();
}
}
外部類(lèi)和成員內(nèi)部類(lèi)的成員重名時(shí),遵循就近原則,如果想要訪(fǎng)問(wèn)外部類(lèi)的成員,使用外部類(lèi)名.成員即可
以上就是深入了解Java內(nèi)部類(lèi)的用法的詳細(xì)內(nèi)容,更多關(guān)于Java內(nèi)部類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis-plus通用查詢(xún)方法封裝的實(shí)現(xiàn)
本文主要介紹了Mybatis-plus通用查詢(xún)方法封裝的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
詳解SpringBoot?統(tǒng)一后端返回格式的方法
今天我們來(lái)聊一聊在基于SpringBoot前后端分離開(kāi)發(fā)模式下,如何友好的返回統(tǒng)一的標(biāo)準(zhǔn)格式以及如何優(yōu)雅的處理全局異常,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-05-05
Springboot整合微信支付(訂單過(guò)期取消及商戶(hù)主動(dòng)查單)
本文主要介紹了Springboot整合微信支付(訂單過(guò)期取消及商戶(hù)主動(dòng)查單),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
關(guān)于maven install報(bào)錯(cuò)原因揭秘:parent.relativePath指向錯(cuò)誤的本地POM文件
在使用Maven進(jìn)行項(xiàng)目構(gòu)建時(shí),如果遇到'parent.relativePath'指向錯(cuò)誤的本地POM文件的問(wèn)題,可能會(huì)導(dǎo)致構(gòu)建失敗,這通常是由于父項(xiàng)目POM文件的相對(duì)路徑設(shè)置錯(cuò)誤、本地POM文件與父項(xiàng)目POM文件版本或內(nèi)容不一致所致,解決方法包括檢查并修正父項(xiàng)目POM文件中的相對(duì)路徑設(shè)置2024-09-09
Spring Data JPA帶條件分頁(yè)查詢(xún)實(shí)現(xiàn)原理
這篇文章主要介紹了Spring Data JPA帶條件分頁(yè)查詢(xún)實(shí)現(xiàn)原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
RabbitMQ?延遲隊(duì)列實(shí)現(xiàn)訂單支付結(jié)果異步階梯性通知(實(shí)例代碼)
這篇文章主要介紹了RabbitMQ?延遲隊(duì)列實(shí)現(xiàn)訂單支付結(jié)果異步階梯性通知,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
Java防止文件被篡改之文件校驗(yàn)功能的實(shí)例代碼
這篇文章主要介紹了Java防止文件被篡改之文件校驗(yàn)功能,本文給大家分享了文件校驗(yàn)和原理及具體實(shí)現(xiàn)思路,需要的朋友可以參考下2018-11-11
java 增強(qiáng)型for循環(huán)語(yǔ)法詳解
增強(qiáng)型 for 循環(huán)(也稱(chēng)為 “for-each” 循環(huán))是 Java 從 JDK 5 開(kāi)始引入的一種便捷循環(huán)語(yǔ)法,旨在簡(jiǎn)化對(duì)數(shù)組或集合類(lèi)的迭代操作,這篇文章主要介紹了java 增強(qiáng)型for循環(huán) 詳解,需要的朋友可以參考下2025-04-04

