Java學習系列(二十三)Java物件導向之內部類詳解

來源:互聯網
上載者:User

標籤:內部類   物件導向   java   對象   匿名內部類   



一、前言

內部類也稱寄生類,就是把一個類放在類裡面(即內部類的上一級程式單元是類)定義,將其作為外部類的成員。內部類主要用幾種定義形式:靜態(static)內部類,非靜態內部類,匿名內部類(也就是沒有名字的寄生類)。內部類的好處就是內部類可以直接外部類的(包括私人)成員,反之不能。下面我們通過一些執行個體來詳細講解一下Java中內部類的使用及幾種定義形式的相互調用。


二、執行個體說明

(1)匿名內部類:當程式建立匿名內部類時,會立即建立匿名內部類(實作類別)的執行個體。

interface IBreathe {void breathe();}/** * 匿名內部類的使用,定義形式如下: *  * new 介面() | 父類構造器<參數>){  * // 類體部分...  * }; *  * @author [*昨日重現*] [email protected] * @since version 1.0 * @datetime 2015年4月29日 下午10:17:40 */public class Anonymous {// 這裡相當於建立了介面IBreathe的匿名實作類別,並建立了匿名內部類的執行個體// 將實作類別的執行個體賦值給介面變數 ,屬於向上轉型IBreathe breathe = new IBreathe() {// 必須實現介面裡的所有抽象方法@Overridepublic void breathe() {System.out.println("呼吸新鮮空氣...");}};public static void main(String[] args) {Anonymous anonymous = new Anonymous();anonymous.breathe.breathe();}}

注意以下幾點:
1)只要父類是抽象類別或者是一個介面,那麼其子類中的方法都可以使用匿名內部類來實現;反過來也就是說使用匿名內部類有個前提:它必須顯示地繼承一個父類或實現一個介面。
2)匿名內部類必須實現介面或抽象類別中所有的抽象方法。
3)匿名內部類適合建立只需一次使用的類。
4)匿名內部類不能有構造器而且程式以後無法再訪問它,因為它沒有類名。


(2)靜態內部類:它屬於外部類(宿主類)的靜態成員,所以它不能訪問外部類的非靜態成員(屬性、方法)。

/** * 外部類(宿主類)中包含靜態內部類作為外部類的一個靜態成員 *  * @author [*昨日重現*] [email protected] * @since version 1.0 * @datetime 2015年4月29日 下午11:00:51 */public class Out {private static String name = "張三";private String sex = "男";static class In {private static String name = "李四";public void info() {// 靜態內部類不能訪問外部類的非靜態成員,所以下面這句會編譯不通過// System.out.println("外部類的sex = " + sex);System.out.println("in的info方法被調用,name:" + name);}}public static void main(String[] args) {// 列印結果(編譯器遵循就近原則):in的info方法被調用,name:李四// 這裡只需要把外部類當成靜態內部類的包就行了// 所以In前加不加Out.都是一樣的new In().info();new Out.In().info();}}

如果要在外部類的外面訪問靜態內部類的成員:Out.In in = new Out.In(); in.info();當然,靜態內部類也可以派生子類:class InSub extends Out.In {},編寫和調用方式與普通類一樣,這裡不再贅述。下面看看重點來看看非靜態內部類定義和使用。


(3)非靜態內部類:在建立非靜態內部類的執行個體前,必須先建立外部類執行個體,也就是說非靜態內部類必須寄生在外部類的執行個體(Outer.this)裡面。所以在建立非靜態內部類的執行個體前,必須先建立外部類執行個體。 

/** * 非靜態內部類的使用 *  * @author [*昨日重現*] [email protected] * @since version 1.0 * @datetime 2015年4月29日 下午11:26:06 */public class Outer {int number = 10;// 定義非靜態內部類class Inner {int number = 100;public void info() {int number = 1000;System.out.println("Inner內部類的info()方法被調用~");System.out.println("number變數的值為:" + number);// 方法的局部變數,所以為1000System.out.println("number變數的值為:" + this.number);// 指向寄生類成員,所以為100System.out.println("number變數的值為:" + Outer.this.number);// 指向宿主類成員,所以為10}}/** * 通過外部類的方法來訪問寄生類的成員(屬性、方法) */public void info() {System.out.println("Outer外部類的info()方法被調用~");Inner inner = new Inner();inner.info();System.out.println(inner.number);}public static void main(String[] args) {new Outer().info();}}
如果在外部類的外面使用內部類,那麼在建立非靜態內部類的執行個體前,必須先建立外部類執行個體。 
Outer outer = new Outer();
Outer.Inner in = outer.new Inner();
等價於==》Outer.Inner in2 = new Outer().new Inner();

當然非靜態內部類也可以派生子類,如下:

//非靜態內部類派生子類class InnerSub extends Outer.Inner {public InnerSub() {// 由於Outer.Inner是非靜態內部類,因此必須使用"宿主對象"來調用它的構造器new Outer().super();}}


三、總結

1)有static修飾的內部類屬於外部類本身,沒有static修飾的內部類屬於類執行個體 。

2)記住方法是誰的,就用誰來調用。

3)沒有static修飾的內部類,【必須寄生在“外部類”的執行個體裡】;反之則寄生在外部類本身裡。

4)靜態內部類是寄生在類本身裡面的,所以就不需要程式員理會宿主。-把外部類當成靜態內部類的包就行了。

5)非靜態內部類派生子類:由於子類的構造器必須調用父類構造器一次,因此必須在子類構造器中使用宿主對象來調用它的構造器。


四、結束語

關於Java中的內部類的定義和使用基本內容就這些,後面會陸續更新包括:Regex、Java效能最佳化、學習JVM等等,敬請關注。


Java學習系列(二十三)Java物件導向之內部類詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.