Java中的內部類(成員內部類、靜態內部類、局部內部類、匿名內部類)
我們先看這樣一段話:人是由大腦、肢體、器官等身體結果組成。而組成我們人體的心臟它也有自己的屬性和行為(血液、跳動),顯然,此處不能單方面用屬性或者方法表示一個心臟了,而需要一個類,但是這個類要依賴於人這個類存在(因為心臟不能脫離人體而存活,當然不考慮現今社會的發達科技,只從正常情況下來說),所心臟以需要寫在人類的內部。內部類就相當於其中的某個器官之一。
首先看看什么是內部類:在類的內部定義另一個類。沒錯,定義就這么簡單。如果在類Outer的內部再定義一個類Inner,此時Inner就稱為內部類,而Outer則稱為外部類。內部類的定義格式如下:
public class 外部類的名稱{ //外部類的成員 public class 內部類的名稱{ //內部類的成員 } }
使用內部類有什么好處;
1)實現多重繼承;
2)內部類可以很好的實現隱藏:一般的非內部類,是不允許有 private 與protected權限的,但內部類可以
3)減少了類文件編譯后的產生的字節碼文件的大小
使用內部類的缺點:使程序結構不清楚。
內部類在編譯完成后也會產生.class文件,但文件名稱是:外部類名稱$內部類名稱.class
內部類的種類:成員內部類、靜態內部類、局部內部類、匿名內部類。下面分別詳細學習一下這四種內部類的具體使用。
一、成員內部類
1、成員內部類也叫實例內部類。應用場合:每一個外部類對象都需要一個內部類的實例,內部類離不開外部類存在(相當於心臟對人體)
2、成員內部類的特征:
作為外部類的一個成員存在,與外部類的屬性、方法並列
成員內部類持有外部類的引用
成員內部類中不能定義static變量和方法
3、使用格式:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
代碼演示一:
/* * 成員內部類 */ public class Body { String arm; String leg; String blood; public Body(String arm, String leg, String blood) { super(); this.arm = arm; this.leg = leg; this.blood = blood; } //內部類Heart class Heart{ String name; void work() { System.out.println("心臟正在給"+arm+leg+"輸"+blood); } }; }
public class Test { public static void main(String[] args) { Body body=new Body("兩個胳膊","兩條腿","血"); Body.Heart heart=body.new Heart(); heart.work(); } }
運行截圖:
代碼演示二:
/* * 成員內部類 */ public class Outer { private String name="Hello World"; public class Inner{ public void print(){ System.out.println(name); } }; public void print(){//定義外部類方法 new Inner().print();//通過內部類的實例化對象調用方法 } public static void main(String[] args) { Outer outer=new Outer(); outer.print();//調用外部類的方法 } }
解釋一下,上述代碼中,new Inner().print();代碼相當於 Inner inner=new Inner(); Inner.print();
二、靜態內部類
1、內部類如果使用static聲明,則此內部類就稱為靜態內部類。(其實也相當於外部類)可以通過外部類 . 內部類來訪問。
2、靜態內部類使用場合:內部類不需要外部類的實例(注意區分成員內部類),靜態內部類存在僅僅為外部類提供服務或者邏輯上屬於外部類,且邏輯上可以單獨存在。
3、靜態內部類的特征:
靜態內部類不會持有外部類的引用
靜態內部類可以訪問外部的靜態變量,如果訪問外部類的成員變量必須通過外部類的實例訪問
4、Java中只有內部類才可以是靜態的
使用格式:Outer.Inner inner = new Outer.Inner();
代碼演示一:
/* * 靜態內部 */ public class Company { String companyNam; static String country; static class Clear{ String name; public Clear() { // TODO Auto-generated constructor stub } public Clear(String name) { super(); this.name = name; } public void work(String name){ String na=new Company().companyNam="聯想"; country="中國"; System.out.println(name+"為"+na+"打掃衛生,該公司屬於"+country); } } }
public class Test { public static void main(String[] args) { Company.Clear zcl=new Company.Clear(); zcl.work("shen_hua"); } }
代碼演示二:
/* * 靜態內部類 */ public class Outer { private static String info="Hello World"; private int i=8; static class Inner{ int num=new Outer().i;//獲取外部類的非靜態成員變量,景天成員變量可以直接使用 public void show() { System.out.println(info+"---"+num); } }; }
public class Test { public static void main(String[] args) { Outer.Inner inner=new Outer.Inner(); inner.show(); } }
三、局部內部類:
1、局部內部類也叫區域內嵌類,局部內部類與成員內部類類似,不過,區域內嵌類是定義在一個方法中的內嵌類。
2、使用場合:如果內部類對象僅僅為外部類的某個方法使用,使用局部內部類
3、特征:
用在方法內部,作用范圍僅限於該方法中
根據情況決定持有外部類對象引用
不能使用private,protected,public修飾符
不能包含靜態成員
代碼演示一:
/* * 局部內部類 */ public class School { String schoolName; String buss="培養人才"; int studentNum; public School() { // TODO Auto-generated constructor stub } public School(String schoolName, String buss, int studentNum) { super(); this.schoolName = schoolName; this.buss = buss; this.studentNum = studentNum; } //宣傳 public void show(){ final double tvMoney=10000; final double netMoney=20000; class AdverTeam{ String teamName="shen_hua"; //電視宣傳 public void tvShow(){ System.out.println("宣傳隊是:"+teamName); System.out.println("這是電視宣傳,學校名稱"+schoolName+",業務內容:"+buss+",學校人數:"+studentNum+",宣傳所需費用"+tvMoney); } //網絡宣傳 public void netShow(){ System.out.println("宣傳隊是:"+teamName); System.out.println("這是網絡宣傳,學校名稱"+schoolName+",業務內容:"+buss+",學校人數:"+studentNum+",宣傳所需費用"+netMoney); } } new AdverTeam().tvShow(); new AdverTeam().netShow(); } }
public class Test { public static void main(String[] args) { School qinghua=new School("清華","互聯網培訓",1000); qinghua.show(); } }
四、匿名內部類
1、如果一個內部類在整個操作中只使用一次的話,就可以定義為匿名內部類。匿名內部類也就是沒有名字的內部類,這是java為了方便我們編寫程序而設計的一個機制,因為有時候有的內部類只需要創建一個它的對象就可以了,以后再不會用到這個類,這時候使用匿名內部類就比較合適。
2、使用場合:簡化內部類的使用
3、特征:
使用new創建 ,沒有具體位置
創建的匿名類,默認繼承或實現new后面的類型
根據使用情況決定是否持有外部類對象引用
內嵌匿名類編譯后生成的.class文件的命名方式是”外部類名稱$編號.class”,編號為1,2,3…n,編號為x的文件對應的就是第x個匿名類
代碼演示:
/* * 匿名內部類 */ public interface Person { public void run(); }
/* * 測試類 */ public class Test { public static void main(String[] args) { Person p=new Person() { public void run() { System.out.println("匿名內部類實現的"); } }; p.run(); } }