【Java】6.7 内部类
目錄
非靜態內部類
靜態內部類
使用內部類
局部內部類
匿名內部類
【內部類是什么?】
內部類 ——?就是把一個類放在類里面定義
內部類 -?寄生類
外部類 -?宿主類
內部類,由于踏上一級程序單元是類,因此他完全可以使用?private |?protected |?默認 |?public?這四個訪問控制符
由于內部的上一級程序單元是類,可以用 static?修飾。有?static?修飾的類屬于外部類本身;沒有?static?修飾的類屬于外部類的實例。
【為什么要引入內部類?】
【注意】非靜態外部類不能擁有靜態內部類。(為什么?)【注釋4】
?
【如何使用內部類?】
非靜態內部類
內部類有一個好處:他可以直接訪問外部類的?private?成員(field/方法/構造器);反過來,外部類不能訪問內部類成員
- 若是沒有?static?修飾的內部類的實例,必須寄生在“外部類”的對象里。
- 若有 static?修飾的內部類的實例,寄生在“外部類”的類本身里
以下代碼表明。調用寄生實例方法之前,必須創建宿主實例
/** * @ClassName: Cow* @description: * @author:FFIDEAL* @Date: 2020年2月27日22:30:24*/ public class Cow {private double weight;public Cow() {}public Cow(double weight) {this.weight = weight;}// 定義一個非靜態內部類private class CowLeg {// 定義兩個非靜態類實例private double length;private String color;public CowLeg() {}public CowLeg(double length, String color) {this.length = length;this.color = color;}public double getLength() {return length;}public void setLength(double length) {this.length = length;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}// 創建非靜態內部類的實例方法public void info() {System.out.println("當前牛腿的顏色是" + color + ",牛腿的長度為" + length);// 可以調用當前外部類的private修飾的成員變量System.out.println("當前牛的體重是:" + weight);}}// 在非靜態內部類中,要創建內部類的實例,首先要創建宿主實例public void test() {CowLeg c1 = new CowLeg(1.12, "黃色");c1.info();}public static void main(String[] args) {Cow cow = new Cow(112.6);cow.test();} }非靜態內部類,也屬于非靜態成員 ——?因為不能被外部靜態成員所訪問
【若查找某個變量時】
當在非靜態內部類的方法訪問某個變量時:在該方法內查找 ->?在方法所在類中查找 ->?在該類的外部類查找 ->系統出現編譯錯誤
/** * @ClassName: DiscernVariable* @description: 描述內部類調用外部類成員變量、內部類成員變量和局部成員變量時的語句* @author: FFIDEAL* @Date: 2020年2月27日 下午10:37:29*//*** @author dell**/ public class DiscernVariable {private String prop = "我在早上學習Java!";// 創建內部類private class InClass {private String prop = "我在中午學習Java!";// 創建內部類的一個測試方法public void info() {String prop = "我在晚上學習Java!";// 通過外部類名.this.varName訪問外部類實例變量System.out.println("外部類的實例變量值為" + DiscernVariable.this.prop);// 通過this.varName訪問外部類實例變量System.out.println("內部類的實例變量值為" + this.prop);// 直接訪問局部變量System.out.println("局部變量值為" + prop);}}// 創建一個方法用于創建內部類的實例public void test() {InClass ic = new InClass();ic.info();}// 創建一個宿主實例,用宿主實例調用上述方法public static void main(String[] args) {DiscernVariable dv = new DiscernVariable();dv.test();} }【注意】在非靜態內部類中,所有的方法、成員變量都屬于實例的。所以在創建內部實例之前,若沒有外部類,則無法獲得外部宿主實例。反之,在static修飾的內部類中,在運行時,已經加載了外部類,存在了宿主類,就可以創建內部靜態類的對象,該對象寄生在外部類中
?
靜態內部類
靜態內部類有?static?修飾,寄生在“外部類”的類本身里,而不屬于任何外部類的實例。靜態內部類可以包含靜態成員,也可以包含非靜態成員。但是靜態內部類的實例方法,也是屬于靜態成員,因此他不能訪問外部類的非靜態成員。
- 以上為什么不能用類名調用?【注釋5】
?
使用內部類
【在外部類以內使用內部類】
若在外部類的里面,使用內部類。并沒有太多需要注意的地方。只需要指導不要在外部類的靜態成員中使用非靜態外部類,因為靜態成員不能訪問非靜態成員。
【在外部類以外使用非靜態內部類】
【在外部類以外使用非靜態內部類】
局部內部類
局部內部類是一個局部成員,和局部變量相似,因此不能用 static 、訪問控制符修飾。局部內部類用?final?修飾是可以的,辨明該局部內部類不能被繼承。局部內部類的作用域實在是太有限了 ——?除了方法就不能使用了。由于局部內部類只能在當前方法中使用,因此使用起來比較簡單。局部內部類的class名為:外部類$N個內部類.class(為什么要有N)【見注釋1】
?
匿名內部類
它是沒有名字的內部類,所以程序以后無法再訪問這個“匿名內部類”。當程序創建匿名內部類時,會立即創建匿名內部類的實例。
//匿名內部類的語法new 接口() | 父類構造器(參數){//類主體 }// —— 上述語法格式實際上返回匿名內部類的實例。程序以后只能使用匿名內部類的實例?
/** * @ClassName: AnonymousTest* @description: 實現接口來創建內部類:new 實現接口* @author: FFIDEAL* @Date: 2020年2月29日 下午2:33:10*/interface Products{public double getPrice();public String getName(); }public class AnonymousTest {//需要傳入一個Product實例public void test(Products p) {System.out.println("購買一個"+p.getName()+",話費了"+p.getPrice());}public static void main(String[] args) {AnonymousTest at = new AnonymousTest();at.test(new Products() {public double getPrice() {return 5560;}public String getName(){return "華為手機";}});} }?
/** * @ClassName: AnonymousInner* @description: 繼承父類創建內部類:new 實現接口,匿名內部類將擁有和父類相似的構造器* @author: FFIDEAL* @Date: 2020年2月29日 下午6:30:06*/ abstract class Device{private String name;public abstract double getPrice();public Device() {}public Device(String name) {this.name = name;}public void setName(String name) {this.name = name;}public String getName() {return name;}}public class AnonymousInner {public void test(Device d) {System.out.println("又買了一個"+d.getName()+",花掉了"+d.getPrice());}public static void main(String[] args) {AnonymousInner ai = new AnonymousInner();//調用有參數的構造器創建Device的匿名類實例對象ai.test(new Device("示波器"){public double getPrice() {return 55.6;}});//調用無參數的構造器Device d = new Device() {//初始化塊{System.out.println("匿名內部類的初始化塊");}//實現抽象方法public double getPrice() {return 56.2;}//重寫父類的方法public String getName() {return "鍵盤";}};ai.test(d);} }【匿名內部類的規則】
【注釋1】因為一個外部類,不同方法中可以定義多個同名的局部內部類
【注釋2】因為匿名內部類需要立即創建市里,因此他不能是抽象的
【注釋3】因為匿名內部類沒有名字,構造器名字不能確定
【注釋4】首先靜態成員不能訪問非靜態成員。若靜態內部類位于非靜態外部類之內,那么靜態內部類不能訪問外部類,且那就失去了靜態內部類存在的意義。
【注釋5】因為類中的static是屬于類本身的。但是static修飾類就與里面非static修飾的方法無關。該方法依然是非靜態方法。靜態內部類屬于外部類而已。非靜態內部類屬于內部類實例。但創建這個內部類實例之前,要確保有外部類的實例這個宿主存在
總結
以上是生活随笔為你收集整理的【Java】6.7 内部类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java】6.6 Java 8 改进的
- 下一篇: 【Java】6.9 枚举类