🔥作者主頁:小林同學的學習筆錄
🔥小林同學的專欄:JAVA之基礎專欄
目錄
1.內部類
1.1 概述
1.1.1 什么是內部類
1.1.2 什么時候使用內部類
1.2 內部類的分類
1.3 成員內部類
1.3.1? 獲取成員內部類對象的兩種方式
1.3.2? 經典面試題
1.4? 靜態內部類
1.4.1? 靜態內部類對象的創建格式
1.5? 局部內部類
1.6? 匿名內部類
1.6.1? 引出匿名內部類?
1.6.2? 匿名內部類用處
1.6.3? 匿名內部類的使用場景
1.內部類
1.1 概述
1.1.1 什么是內部類
將一個類A定義在另一個類B里面,里面的那個類A就稱為內部類,B則稱為外部類,其他稱為外部其他類。可以把內部類理解成寄生,外部類理解成宿主。
1.1.2 什么時候使用內部類
一個事物內部還有一個獨立的事物,內部的事物脫離外部的事物無法獨立使用
-
人里面有一顆心臟。
-
汽車內部有一個發動機。
-
目的為了實現更好的封裝性。
1.2 內部類的分類
按定義的位置來分
-
成員內部內,類定義在了成員位置 (類中方法外稱為成員位置,無static修飾的內部類)
-
靜態內部類,類定義在了成員位置 (類中方法外稱為成員位置,有static修飾的內部類)
-
局部內部類,類定義在方法內
-
匿名內部類,沒有名字的內部類,可以在方法中,也可以在類中方法外。
1.3 成員內部類
類定義在成員位置上
1.3.1? 獲取成員內部類對象的兩種方式
- 方式一:外部直接創建成員內部類的對象
- 外部類.內部類 變量 = new 外部類().new 內部類();
- 方式二:在外部類中定義一個方法提供內部類的對象(一般用在內部類用private修飾才用到)
代碼演示:
方式一:
public class Test {public static void main(String[] args) {// 宿主:外部類對象。// Outer out = new Outer();// 創建內部類對象。Outer.Inner oi = new Outer().new Inner();oi.method();}
}class Outer {// 成員內部類,屬于外部類對象的。// 拓展:成員內部類不能定義靜態成員。public class Inner{// 這里面的東西與類是完全一樣的。public void method(){System.out.println("內部類中的方法被調用了");}}
}方式二:
public class Outer {String name;private class Inner{static int a = 10;}public Inner getInstance(){return new Inner();}
}public class Test {public static void main(String[] args) {Outer o = new Outer();System.out.println(o.getInstance());}
}
1.3.2? 經典面試題
public class Test {public static void main(String[] args) {Outer.inner oi = new Outer().new inner();oi.method();}
}class Outer { // 外部類private int a = 30;// 在成員位置定義一個類class inner {private int a = 20;public void method() {int a = 10;System.out.println(???); // 10 答案:aSystem.out.println(???); // 20 答案:this.aSystem.out.println(???); // 30 答案:Outer.this.a}}
}
執行原理:
?
1.4? 靜態內部類
靜態內部類可以直接訪問外部類的靜態成員。
靜態內部類不可以直接訪問外部類的非靜態成員,如果要訪問需要創建外部類的對象。
靜態內部類中沒有虛擬機所創建的Outer.this
如何調用靜態內部類的方法?
- 非靜態方法:創建對象,并調用方法
- 靜態方法:外部類名.內部類名.方法名()
1.4.1? 靜態內部類對象的創建格式
外部類.內部類 ?變量 = new ?外部類.內部類構造器;
代碼演示:
// 外部類:Outer01
class Outer01{private static String sc_name = "小白";private String sc_age = 24;// 內部類: Inner01public static class Inner01{// 這里面的東西與類是完全一樣的。private String name;public Inner01(String name) {this.name = name;}public void showName(){System.out.println(this.name);// 拓展:靜態內部類可以直接訪問外部類的靜態成員。System.out.println(sc_name);//訪問外部類的非靜態的變量需要創建外部類的對象Outer01 outer01 = new Outer01();System.out.println(outer.sc_age);}}
}public class InnerClassDemo01 {public static void main(String[] args) {// 創建靜態內部類對象。// 外部類.內部類 變量 = new 外部類.內部類構造器;Outer01.Inner01 in = new Outer01.Inner01("張三");in.showName();}
1.5? 局部內部類
將內部類定義在方法里面就叫做局部內部類,類似于方法中的局部變量
外部類是無法直接獲取局部內部類的,需要創建該類的對象,然后再進行使用
該類可以直接訪問外部類的成員,也可以訪問方法內的局部變量
public class Outer {private int outerField = 10;public void outerMethod() {final int localVar = 20;//局部內部類class LocalInner {void display() {System.out.println("Outer Field: " + outerField);System.out.println("Local Variable: " + localVar);}}//外部類獲取內部類信息,需要創建對象LocalInner inner = new LocalInner();inner.display();}public static void main(String[] args) {Outer outer = new Outer();outer.outerMethod();}
}
1.6? 匿名內部類
1.6.1? 引出匿名內部類?
正常類:
?
匿名內部類(Student被匿名):
?
代碼演示:
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 使用匿名內部類對象,并且調用匿名內部類里面的方法new Swim() {@Overridepublic void swimming() {System.out.println("自由泳...");}}.swimming();// 接口 變量 = new 實現類(); // 多態,走子類的重寫方法Swim s2 = new Swim() {@Overridepublic void swimming() {System.out.println("蛙泳...");}};s2.swimming();s2.swimming();}
}
注意:
new Swim(){@Overridepublic void swim() {System.out.println("Demo01匿名內部類");} };
這樣的話是不會有打印數據的,因為整體只是一個匿名內部類對象,需要再去調用相應的成員
?
匿名內部類字節碼文件反編譯看到的效果
?
實際案例:
public class Test01 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("11");list.add("12");list.add("13");//下面就是一個匿名內部類list.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});}
}
反編譯之后
?
1.6.2? 匿名內部類用處
匿名內部類在Java中有著一些重要的用途,其中包括:
-
簡化代碼:使用匿名內部類可以減少代碼量,避免編寫大量的類定義。
-
事件處理器:在GUI編程中常常使用匿名內部類來實現事件處理器,如按鈕點擊事件、菜單項選擇等。
-
回調函數:匿名內部類也可以用作回調函數的實現,例如對異步任務的處理。
-
接口實現:如果只需要使用接口的一次實例,可以直接使用匿名內部類來實現接口的抽象方法。
-
方法重寫:可以在匿名內部類中重寫父類或接口的方法,以實現特定的邏輯。
總之,匿名內部類提供了一種簡潔、靈活的方式來實現某些具體功能,通常用于臨時、一次性的場景中。
1.6.3? 匿名內部類的使用場景
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 普通方式傳入對象// 創建實現類對象Student s = new Student();goSwimming(s);// 匿名內部類使用場景:作為方法參數傳遞Swim s3 = new Swim() {@Overridepublic void swimming() {System.out.println("蝶泳...");}};// 傳入匿名內部類goSwimming(s3);// 完美方案: 一步到位goSwimming(new Swim() {public void swimming() {System.out.println("大學生, 蛙泳...");}});goSwimming(new Swim() {public void swimming() {System.out.println("小學生, 自由泳...");}});}// 定義一個方法,模擬請一些人去游泳public static void goSwimming(Swim s) {s.swimming();}
}
總結:
?