?找往期文章包括但不限于本期文章中不懂的知識點:
個人主頁:我要學編程(?_?)-CSDN博客
所屬專欄:JavaSE
目錄
內部類的概念?
內部類的種類
使用舉例:
1. 靜態內部類:
2. 實例內部類
3. 局部內部類
4. 匿名內部類
內部類的概念?
當一個事物的內部,還有一個部分需要一個完整的結構進行描述,而這個內部的完整的結構又只為外部事物提供服 務,那么這個內部的完整結構最好使用內部類。在 Java 中,可以將一個類定義在另一個類或者一個方法的內部, 前者稱為內部類,后者稱為外部類。內部類也是封裝的一種體現。
最常見的語法格式:
// OutClass是外部類
// InnerClass是內部類public class OutClass {//……class InnerClass{//……}//……
}
注意:內部類和外部類共用同一個 .java后綴 的源文件,但是經過編譯之后,內部類會形成單獨的字節碼文件。?如下:
?
細心的小伙伴應該也已經發現了:內部類的類名前面有其所在的外部類類名加上一個$符號。這個就是用來區分的。就是告訴我們,A這個類是Test這個類中的內部類。
那么外部類和不同的類相比,有什么變化呢?其實沒什么變化,我們就可以把內部類看成是外部類的一個成員變量,僅僅只是多個成員變量而已。因此可以把內部類看成是一個成員變量。
內部類的種類
內部類其實有很多種。?根據其所處的位置不同,分為3種。?
1. 實例內部類。其所處的位置是成員變量的位置,并且沒有被 static 修飾。
// 外部類
public class Test {// 實例內部類class A {}
}
2. 靜態內部類。同樣是在成員變量的位置,不過有個 static 修飾它。
public class Test {// 靜態內部類static class B {}
}
3. 局部內部類。在方法內定義的類。這種類用的比較少,因為它的作用域有限。?
public class Test {public static void main(String[] args) {// 局部內部類class C {}}
}
注意:局部內部類不能被 static 修飾,就和局部變量一樣。被 static 修飾的都是類的屬性和方法了,其作用域都已經改變了,和 “局部” 兩個字發生了沖突。
4. 還有一種不是根據所處的位置定義的,那就是匿名內部類。
匿名內部類沒有名字,直接在創建對象時定義并實例化,常用于實現接口或繼承抽象類。雖然匿名內部類并非強制要求在方法中使用,實踐中幾乎總是將其放在方法內以體現其臨時性和局部性,便于管理和理解代碼。
public class Test {public static void main(String[] args) {// 匿名內部類new Test() {};}
}
使用舉例:
1. 靜態內部類:
// 外部類
public class Test {public static int a = 1;public static int b = 2;public static int c = 3;// 靜態內部類static class B {public static int d = 4;public static int e = 5;public static int a = 100; // 和外部類的成員變量名相同public int f = 6;public static void main(String[] args) {// 由于main方法時靜態方法,不創建對象的情況下,只能訪問靜態的東西。// 因此變量全部都是static修飾的。// 當外部類和內部類同名時,要通過外部類對象的引用或者類名來訪問System.out.println(Test.a);System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(d);System.out.println(e);// 雖然靜態內部類中可以有非靜態的成員變量和方法,但是卻還是不能在靜態方法中使用// System.out.println(f);}}
}
?運行結果:
如果要在外部訪問靜態內部類怎么做呢?其實就是和訪問靜態成員變量是一樣的。通過類名來訪問。如下:
2. 實例內部類
// 外部類
public class Test {public int a = 1;public static int b = 2;public int c = 3;public int d = 4;// 實例內部類class B {public int f = 5;public int e = 6;public int a = 100;public void func(){// 同樣有同名的變量是優先訪問自己的System.out.println(a);// 如果想要訪問外部的,得通過 外部類名稱.this.同名成員名字 的方法System.out.println(Test.this.a);}}
}
如果想要創建內部類對象,該怎么做呢?
public class TestDrive {public static void main(String[] args) {// 通過外部類訪問內部類// 法一:Test.B tb = new Test().new B();// 法二:Test test = new Test();test.B tb = tset.new B();tb.func();}
}
我們把這個實例內部類看成是一個實例成員變量就好了,用訪問實例成員的方法來訪問實例內部類。而實例成員是通過對象的引用來訪問的。?
既然類型是通過外部類來訪問內部類的,那么對象的創建也應如此:先創建外部類對象,再通過外部類對象來創建內部類對象。
注意:
1. 外部類中的任何成員都可以在實例內部類方法中直接訪問。
2. 在實例內部類方法中訪問同名的成員時,優先訪問自己的,如果要訪問外部類同名的成員,必須:外部類名 稱.this.同名成員 來訪問。因為實例內部類本身也有一個屬于自己的 this 。
3. 實例內部類對象必須在先有外部類對象前提下才能創建。
5. 實例內部類的非靜態方法中包含了一個指向外部類對象的引用。這個引用不是顯式地在代碼中聲明的,而是由Java編譯器自動添加的。在內部類的方法中,你可以直接使用外部類的成員變量和方法,就像它們是內部類自己的一樣。實際上,編譯器會在內部類的方法代碼中插入必要的代碼來通過這個隱含的引用訪問外部類的成員。
6. 外部類中,不能直接訪問實例內部類中的成員,如果要訪問必須先要創建內部類的對象。因為內部類中的成員作用域是只在內部類中。可以理解為在另一個類中訪問一個與其不相干的類,自然要通過對象的引用來訪問,也就是需要創建一個對象。
3. 局部內部類
// 外部類
public class Test {public static void main(String[] args) {// 局部內部類class B {public int a;public int b;public void func() {System.out.println("這是內部類中的方法...");}}// 只能在定義的方法內部使用B b = new B();b.func();}
}
注意:
1. 局部內部類既然是在方法內部定義的,那么它們的作用域也只能是在方法內部。
2. 局部內部類不能被public 、 static 等修飾符修飾。因為public 、static 修飾的都是類中的變量或者方法,怎么可能會去修飾局部變量的呢?
4. 匿名內部類
雖然匿名內部類多是在有抽象類和接口的情況下使用,但并不意味著不能普通類不能有匿名內部類。
普通類:?
// 普通類
class A {public void func() {System.out.println("這是普通類的方法...");}
}// 外部類
public class Test {public static void main(String[] args) {// 這是匿名對象,也就是創建了一個沒有對象引用的對象// 正因如此,這個對象只能使用一次,匿名內部類同樣如此new A();// 匿名內部類new A(){// 匿名內部類的使用就是為了重寫抽象類和接口的方法@Overridepublic void func() {super.func(); // 可以理解為:繼承這個普通類之后,又重寫了其中的方法}}.func(); // 這里就是在調用這個對象的方法 }
}
抽象類:
// 抽象類
abstract class B {public abstract void func();
}// 外部類
public class Test {public static void main(String[] args) {new B(){@Overridepublic void func() {System.out.println("可以理解為:繼承了B這個抽象類,并重寫了B這個抽象類中的方法");}}.func();}
}
接口:
// 接口
interface C {void func();
}// 外部類
public class Test {public static void main(String[] args) {new C(){@Overridepublic void func() {System.out.println("可以理解為:實現了C這個接口,并重寫了C這個接口中的方法");}}.func();}
}
上面就是匿名內部類的使用方法。?
注意:
1. 在匿名內部類中可以使用對象的引用去接收,但是不能再其后面調用方法了,而是要通過對象的引用來調用方法。如下(注意對比):
好啦!本期?初始Java篇(JavaSE基礎語法)—— 內部類 的學習之旅就到此結束啦!我們下一期再一起學習吧!