全面探究 Java 內(nèi)部類
內(nèi)部類(inner class)是定義在另一個類中的類。為什么要使用內(nèi)部類呢?主要有兩個原因:1.內(nèi)部類可以對同一個包中的其他類隱藏。2.內(nèi)部類方法可以訪問定義這個類的作用域中的數(shù)據(jù),包括原本私有的數(shù)據(jù)。
下面,我就來帶領(lǐng)大家去學(xué)習(xí)Java中比較常見的幾種內(nèi)部類,希望對大家有一定的收獲!
一. 實(shí)例內(nèi)部類
1. 定義
什么是實(shí)例內(nèi)部類呢?顧名思義,就是在一個普通類的內(nèi)部再定義一個類,即為實(shí)例內(nèi)部類。
如:
class OuterClass{
public int data1=1;
public static int data2=2;
class InnerClass{
public int data3=3;
}
}
但是應(yīng)該注意實(shí)例內(nèi)部類里不能有static修飾的靜態(tài)成員變量,我們可以把實(shí)例內(nèi)部類當(dāng)做類中的一個實(shí)例成員,那么當(dāng)我們調(diào)用它的時候,可以認(rèn)為調(diào)用的過程是依賴于對象的,但是static又不依賴于對象,因此我們可以推出不能有static修飾的字段。如果非要使用靜態(tài)的,那么必須再加上final,即用static final來修飾,因為用final修飾后的值是無法更改的,可以把它當(dāng)做是一個常量,即在編譯期間可以確定它的值,這樣就不會報錯了
2. 如何獲取實(shí)例內(nèi)部類這個對象的引用
在創(chuàng)建好一個內(nèi)部類后,我們該如何訪問內(nèi)部類里的成員屬性呢?一般通過new 兩次對象來獲?。?/p>
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
當(dāng)然我們也可以通過匿名對象的方法直接獲取:
OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass();
此處的語法還是比較繞的如果實(shí)在理解不了的話直接記住就行~
3. 注意事項
當(dāng)實(shí)例內(nèi)部類中與外部類有同名的成員變量時,通過實(shí)例內(nèi)部類去訪問這個成員變量會訪問實(shí)例內(nèi)部類自己的,例如:
class OuterClass{
public int data1=1;
public static int data2=2;
class InnerClass{
public int data1=10;
}
}
public class TestDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
System.out.println(innerClass.data1);
}
}
運(yùn)行結(jié)果為:

那么我們?nèi)绾瓮ㄟ^實(shí)例內(nèi)部類的引用去訪問外部類中的data1呢?方法如下:
class OuterClass{
public int data1=1;
public static int data2=2;
class InnerClass{
public int data1=10;
public void func(){
System.out.println(data1);
System.out.println(this.data1);//this為自己的對象的引用
System.out.println(OuterClass.this.data1);//this為外部類對象的引用
}
}
}
public class TestDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.func();
}
}
打印結(jié)果為:

二. 靜態(tài)內(nèi)部類
1. 定義
和實(shí)例內(nèi)部類一樣,我們也可以把靜態(tài)內(nèi)部類當(dāng)做外部類的一個成員屬性,只不過是靜態(tài)的
代碼演示如下:
class OuterClass{
public int data1=1;
public static int data2=2;
static class InnerClass{
public int data1=10;
public static int data2=20;
public void func(){
System.out.println(data1);
System.out.println(this.data1);
System.out.println(OuterClass.this.data1);
}
}
}
注意,靜態(tài)內(nèi)部類中可以定義靜態(tài)的成員屬性了
2. 如何獲取靜態(tài)內(nèi)部類這個對象的引用
和獲取實(shí)例內(nèi)部類對象引用的方法差不多,但稍有變動:OuterClass.InnerClass innerClass=new OuterClass.InnerClass();
3. 注意事項
同樣,我們也有一些需要注意的問題,在靜態(tài)內(nèi)部類當(dāng)中,我們不能訪問外部類的非靜態(tài)數(shù)據(jù)成員。
因為靜態(tài)內(nèi)部類不依賴于對象,而外部類不是靜態(tài)的,是依賴于對象的,如果非要訪問,我們可以在內(nèi)部類中構(gòu)造一個外部類對象的引用out
代碼示例如下:
class OuterClass{
public int data1=1;
public static int data2=2;
static class InnerClass{
public int data1=10;
public static int data2=20;
public OuterClass out;
public InnerClass(OuterClass o){
this.out=o;
}
public void func(){
System.out.println(data1);
System.out.println(this.out.data1);
}
}
}
public class TestDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass=new OuterClass.InnerClass(outerClass);
innerClass.func();
}
打印結(jié)果為:

三. 匿名內(nèi)部類
1. 定義
匿名內(nèi)部類是一個用法較為簡單的類,寫法示例如下:
class OuterClass{
public void func(){
System.out.println("匿名內(nèi)部類");
}
}
public class TestDemo{
public static void main(String[] args) {
new OuterClass(){
//此處為匿名內(nèi)部類
};
}
}
當(dāng)然,在匿名內(nèi)部類中也可以重寫外部類中的方法:
lass OuterClass{
public void func(){
System.out.println("匿名內(nèi)部類");
}
}
public class TestDemo{
public static void main(String[] args) {
new OuterClass(){
@Override
public void func() {
System.out.println("此處為重寫后的func方法");
}
};
}
}
調(diào)用重寫后的方法步驟如下:
public static void main(String[] args) {
new OuterClass(){
@Override
public void func() {
System.out.println("此處為重寫后的func方法");
}
}.func();
}
打印結(jié)果:

注意,匿名內(nèi)部類只定義一次且沒有名字
2. 常見用法
interface A {
public void func();
}
A a = new A(){
@Override
public void func() {
System.out.println("當(dāng)前是個匿名內(nèi)部類,實(shí)現(xiàn)了A接口,重寫了接口的方法");
}
};
上面部分的代碼為匿名內(nèi)部類,這個內(nèi)部類實(shí)現(xiàn)了A接口并且重寫了A接口中的方法
3. 注意事項
匿名內(nèi)部類中有一個變量捕獲機(jī)制,即匿名內(nèi)部類中變量的值是無法修改的
public static void main(String[] args) {
int flag=1;
new OuterClass(){
@Override
public void func() {
System.out.println("此處為重寫后的func方法");
System.out.println(flag);
}
}.func();
}
此時我們的程序可以正常運(yùn)行,打印的結(jié)果為1

然而,當(dāng)我們修改flag的值后,程序會報錯:

因此,需要牢記匿名內(nèi)部類中的變量捕獲機(jī)制,即無法二次修改變量的值?。?!
好啦,本期有關(guān)內(nèi)部類的分享就到此結(jié)束了,大家一起加油鴨!

到此這篇關(guān)于全面探究 Java 內(nèi)部類的文章就介紹到這了,更多相關(guān)Java 內(nèi)部類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring基于注解管理bean實(shí)現(xiàn)方式講解
很多時候我們需要根據(jù)不同的條件在容器中加載不同的Bean,或者根據(jù)不同的條件來選擇是否在容器中加載某個Bean,這就是Bean的加載控制,一般我們可以通過編程式或注解式兩種不同的方式來完成Bean的管理2023-01-01
Java 調(diào)用天氣Webservice詳解及實(shí)例代碼
這篇文章主要介紹了Java 調(diào)用天氣Webservice詳解及實(shí)例代碼的相關(guān)資料,這里附實(shí)例代碼,使用java 調(diào)用webservice 的小應(yīng)用,需要的朋友可以參考下2016-11-11
關(guān)于HashMap的put方法執(zhí)行全過程
這篇文章主要介紹了關(guān)于HashMap的put方法執(zhí)行全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
解析Java實(shí)現(xiàn)設(shè)計模式六大原則之里氏替換原則
里氏替換原則是用來幫助我們在繼承關(guān)系中進(jìn)行父子類的設(shè)計。它闡述了有關(guān)繼承的一些原則,也就是什么時候應(yīng)該使用繼承,什么時候不應(yīng)該使用繼承,以及其中蘊(yùn)含的原理。它是繼承復(fù)用的基礎(chǔ),反映了基類與子類之間的關(guān)系,是對開閉原則的補(bǔ)充,對實(shí)現(xiàn)抽象化具體步驟的規(guī)范2021-06-06
SpringBoot整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息的實(shí)例代碼
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息的相關(guān)資料,需要的朋友可以參考下2023-03-03

