溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解Java編程中的內(nèi)部類

發(fā)布時(shí)間:2021-11-20 16:23:48 來(lái)源:億速云 閱讀:97 作者:柒染 欄目:編程語(yǔ)言

怎么理解Java編程中的內(nèi)部類,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

內(nèi)部類:在其它類內(nèi)定義的類,不同于組合。雖然看上去象某種代碼隱藏機(jī)制,但可以實(shí)現(xiàn)更多功能 -了解包含它的類并可與之交換數(shù)據(jù),而且內(nèi)部類的代碼可以更優(yōu)雅、清晰。

內(nèi)部類定義:包含在其它類內(nèi)。使用與非內(nèi)部類沒(méi)有太大區(qū)別。

典型用法:outer class通過(guò)方法返回inner class的引用。

區(qū)別之一:內(nèi)部類名嵌套在外部類(outer class)內(nèi),在Out class的non-static方法之外用OuterClassName.InnerClassName的形式定義內(nèi)部類對(duì)象。

注意,非static內(nèi)部類只能在Out class的non-static方法中生成對(duì)象;在其它類中,也必須使用Out class的外部類對(duì)象實(shí)例。這就保證了下面所說(shuō)的鏈接問(wèn)題。

區(qū)別之二:內(nèi)部類可以為private和protected。

Inner Class只是一種名稱隱藏(name-hiding)和組織代碼方式?NO。

內(nèi)部類對(duì)象有一個(gè)到創(chuàng)建它的外部類對(duì)象的鏈接(link to the enclosing object that made it),因而可以直接的、沒(méi)有任何限制地訪問(wèn)該外部類對(duì)象的成員,而且內(nèi)部類可以訪問(wèn)outer class的所有成員(包括private)(C++的嵌套類沒(méi)有這個(gè)特性);而outer class訪問(wèn)inner class的成員,必須創(chuàng)建Inner class的對(duì)象,可以訪問(wèn)任何成員(包括private)。

內(nèi)部類對(duì)象中隱式包含了一個(gè)外部類對(duì)象的引用。內(nèi)部類對(duì)象構(gòu)建需要outer class對(duì)象的引用,如果沒(méi)有,編譯報(bào)錯(cuò)(非靜態(tài)inner class)。

.this和.new:前者用來(lái)返回Outer class引用,編譯期可知道和檢查正確類型,無(wú)運(yùn)行時(shí)開(kāi)銷;后者用來(lái)由outer class對(duì)象創(chuàng)建其內(nèi)部類的對(duì)象,OutClassObject.new InnerClassName ()(注意,不能用outClassObj.new OutClassName.InnerClassName())。

嵌套類(nested class):static inner class,其對(duì)象創(chuàng)建不需要outer class對(duì)象引用,也可在static方法中創(chuàng)建。

內(nèi)部類與upcasting

類實(shí)現(xiàn)了接口(interface),其它方法就可以用該interface作為參數(shù),而不一定必須用該類(包括類對(duì)象定義)(類似繼承)。可以利用upcasting->interface。

upcasting內(nèi)部類->基類或者接口(尤其是后者),使內(nèi)部類有了用武之地。實(shí)現(xiàn)接口內(nèi)部類可以完全不可見(jiàn)、不可用(通過(guò)private或protected),所獲得的只是基類或接口的引用(通過(guò)private,無(wú)法進(jìn)行downcasting,protected,同一個(gè)包內(nèi),或者繼承類可以進(jìn)行downcasting),方便隱藏實(shí)現(xiàn)細(xì)節(jié)。

接口成員自動(dòng)為public

private內(nèi)部類可以阻止任何依賴于類型的代碼,進(jìn)行所有實(shí)現(xiàn)細(xì)節(jié)的隱藏。而且,擴(kuò)展接口也沒(méi)有任何意義,因?yàn)闊o(wú)法訪問(wèn)pubic接口之外的方法,這可以使JAVA產(chǎn)生更有效率的代碼 。

inner class可以在任意作用域內(nèi)定義(如方法內(nèi))。

兩個(gè)理由:1. 實(shí)現(xiàn)一個(gè)接口

2. 需要一個(gè)不公開(kāi)的類輔助解決復(fù)雜的問(wèn)題

inner class形式

1. 方法內(nèi)的內(nèi)部類; 2. 方法中的一個(gè)作用域內(nèi)的內(nèi)部類; 3. 實(shí)現(xiàn)接口的匿名內(nèi)部類; 4. 繼承的匿名內(nèi)部類(基類含有參的構(gòu)造器); 4. 進(jìn)行成員初始化的匿名內(nèi)部類; 5. 使用實(shí)例初始化塊進(jìn)行構(gòu)造的匿名內(nèi)部類(匿名類沒(méi)有構(gòu)造器)。

局部?jī)?nèi)部類(local inner class) :在方法內(nèi)或方法的一個(gè)作用域中定義的內(nèi)部類。局部?jī)?nèi)部類在域外不可見(jiàn)并不代表其對(duì)象也不可用。條件域內(nèi)定義的內(nèi)部類不代表它是條件創(chuàng)建的。

匿名內(nèi)部類(anonymous inner class) :new T(){...}; {...}為匿名內(nèi)部類的定義,";"不可少(;只是該語(yǔ)句的結(jié)束,而不是用來(lái)表示匿名內(nèi)部類的結(jié)束,所以沒(méi)有什么特殊的地方),創(chuàng)建一個(gè)繼承自T的匿名類的對(duì)象,得到的引用可自動(dòng)upcast to T。是前面定義內(nèi)部類的一種簡(jiǎn)寫(xiě),只是該類沒(méi)有名稱。

前面是基類構(gòu)造器為默認(rèn)構(gòu)造器的情況,當(dāng)基類構(gòu)造器有參數(shù)時(shí):new T(args){...};此時(shí)會(huì)調(diào)用基類相應(yīng)構(gòu)造器。

匿名內(nèi)部類初始化 :當(dāng)需要用到外部定義類的對(duì)象時(shí),傳遞的引用參數(shù)必須為final,否則編譯報(bào)錯(cuò);匿名類不能有命名的構(gòu)造器(當(dāng)然不能,類本身就沒(méi)有名字),可以通過(guò)實(shí)例初始化(instance initialization)來(lái)完成構(gòu)造器的功能。由于實(shí)例初始化不能重載(不代表只能有一個(gè)Instance initialization clause),所以匿名內(nèi)部類只能有一個(gè)構(gòu)造器。

匿名內(nèi)部類只能在繼承類和實(shí)現(xiàn)接口中2選一,且只能實(shí)現(xiàn)一個(gè)接口。

prefer classes to interfaces. (寧愿選擇類,而不是接口?)

嵌套類(nested class):static inner class。有點(diǎn)類似C++嵌套類的概念,但Java的嵌套類可以訪問(wèn)outer class的所有成員(包括private,當(dāng)然只能通過(guò)外部類對(duì)象訪問(wèn)non-static成員)。

1. 不需要通過(guò)outer class對(duì)象來(lái)創(chuàng)建嵌套類對(duì)象(.new不可用?);

2. 不能通過(guò)嵌套類對(duì)象訪問(wèn)non-static outer class對(duì)象(意思是像非嵌套類那樣直接訪問(wèn));

3. 嵌套類對(duì)象中不包含outer class對(duì)象引用(.this不可用)。

4. 非嵌套內(nèi)部類不能有static成員、方法和嵌套類(fields、methods級(jí)別必須與class本身一致,non-static不能含有static,non-static、static內(nèi)可以含有non-static)。

嵌套類可以位于接口內(nèi)部,不違反接口的規(guī)則(不能定義接口實(shí)例?),只代表把嵌套類位于接口的命名空間下,位于接口內(nèi)部的類自動(dòng)為public static(public嵌套類),而且嵌套類本身就可以實(shí)現(xiàn)該接口,好處在于可以在嵌套類內(nèi)編寫(xiě)該接口所有實(shí)現(xiàn)中都要用到的代碼。

嵌套類的另一個(gè)用途:編寫(xiě)測(cè)試代碼。 為每個(gè)類編寫(xiě)main函數(shù)增加代碼長(zhǎng)度,可以把main放在嵌套類內(nèi),要測(cè)試該類運(yùn)行該嵌套類即可;而在發(fā)布的時(shí)候只要在打包前簡(jiǎn)單的刪除該嵌套類的.class文件即可。

多重嵌套的類(non-static和static)可以沒(méi)有限制的訪問(wèn)任何外層類的所有對(duì)象。

為什么用內(nèi)部類?

不是總是直接和接口打交道,有時(shí)候需要用的是接口的實(shí)現(xiàn)。(可以實(shí)現(xiàn)多個(gè)接口,但不能繼承多個(gè)類)

理由:每個(gè)內(nèi)部類可以獨(dú)立繼承自一個(gè)實(shí)現(xiàn),不受outer class是否已經(jīng)繼承另一實(shí)現(xiàn)的限制。從效果上來(lái)說(shuō),inner class提供了多繼承(multiple-inheritance,繼承自多個(gè)類)的能力,提供了另一種實(shí)現(xiàn)多個(gè)接口的方法(相比多繼承,這個(gè)似乎沒(méi)那么重要,因?yàn)槎嗬^承只能通過(guò)內(nèi)部類來(lái)實(shí)現(xiàn))。

額外特性:

1. 內(nèi)部類可以有多個(gè)實(shí)例,每個(gè)實(shí)例可以擁有獨(dú)立于outer class對(duì)象的不同信息;

2. 一個(gè)outer class可以有多個(gè)內(nèi)部類,每個(gè)內(nèi)部類可以以不同的方式實(shí)現(xiàn)同一個(gè)接口或者繼承同一個(gè)類(參見(jiàn)習(xí)題22,兩個(gè)內(nèi)部類不同方式實(shí)現(xiàn)同一個(gè)接口,只有內(nèi)部類才能完成這些);

3. 內(nèi)部類實(shí)例創(chuàng)建時(shí)間并不受到外部類對(duì)象創(chuàng)建的限制;

4. 用內(nèi)部類不會(huì)制造"is-a"關(guān)系的混亂,每個(gè)內(nèi)部類都是個(gè)實(shí)體。

閉包(closure)和回調(diào)(callback)

閉包是一種可調(diào)用的對(duì)象,它記錄了來(lái)自創(chuàng)建它的作用域的一些信息。

內(nèi)部類是一種面向?qū)ο蟮拈]包,不僅包含了外部類的信息,而且通過(guò)包含一個(gè)指向外部類對(duì)象的引用,可以操作所有成員,包括private。

回調(diào),通過(guò)其它對(duì)象攜帶的信息,可以在稍后的某個(gè)時(shí)刻調(diào)用初始對(duì)象。

Java不支持指針類型,不能通過(guò)指針來(lái)實(shí)現(xiàn)回調(diào)。但內(nèi)部類提供的閉包是種比較好的解決方案,更靈活,更安全(參見(jiàn)例callbacks)。

private class Closure implements Incrementable {       public void increment() {       // Specify outer-class method, otherwise       // you’d get an infinite recursion:           Callee2.this.increment();       }   }

回調(diào)的價(jià)值在于靈活性,可以在運(yùn)行時(shí)決定需要調(diào)用的方法。 GUI編程將體現(xiàn)得更明顯。

內(nèi)部類與控制框架(control frameworks)

一個(gè)應(yīng)用程序框架(application framework)是指一個(gè)用來(lái)解決一個(gè)特定類型問(wèn)題的類或類的集合。典型的應(yīng)用方法是,繼承其中一個(gè)或多個(gè)類,重寫(xiě)某些方法。重寫(xiě)方法的代碼將通用解決方案特殊化,來(lái)解決特定問(wèn)題。例如模板函數(shù)模式。 設(shè)計(jì)模式將不變的和變化的事情分開(kāi)。

控制框架是用來(lái)響應(yīng)事件的一類特殊的應(yīng)用程序框架 。主要用來(lái)響應(yīng)事件的系統(tǒng)稱為事件驅(qū)動(dòng)系統(tǒng)(event-driven system),如GUI。

內(nèi)部類使得控制框架的創(chuàng)建和使用變得簡(jiǎn)單 ??刂瓶蚣鼙旧聿话ㄒ刂频氖挛锏奶囟ㄐ畔?。這些信息在繼承過(guò)程中,由算法的action()部分實(shí)現(xiàn)時(shí)提供??刂瓶蚣苤凶兓氖虑槭歉鞣N事件對(duì)象的不同action,這通過(guò)創(chuàng)建不同event繼承類來(lái)實(shí)現(xiàn)。(例event)

控制事件用abstract類代替接口?

內(nèi)部類在控制框架中兩個(gè)作用:

1. 用來(lái)表示解決問(wèn)題所需的各種不同的action()。

2. 內(nèi)部類可以直接訪問(wèn)外部類的所有成員,因而使得實(shí)現(xiàn)變得更靈活。

參見(jiàn)greenhouse(溫室)的例子。

內(nèi)部類的繼承

內(nèi)部類指向outer class object的引用必須初始化,而在它的繼承類中并不存在要聯(lián)接的缺省對(duì)象,必須使用特殊的語(yǔ)法明確指出這種關(guān)聯(lián)。

繼承自內(nèi)部類的類構(gòu)造器不能是默認(rèn)構(gòu)造器,要有個(gè)outer class的引用作為參數(shù),而且必須加上enclosingClassReference.super();語(yǔ)句,編譯才能通過(guò)。

內(nèi)部類能override?繼承outer class,像重寫(xiě)方法一樣重寫(xiě)內(nèi)部類并不起作用,此時(shí)兩個(gè)內(nèi)部類只是兩個(gè)獨(dú)立的實(shí)體。可以顯式指定內(nèi)部類的繼承關(guān)系,然后通過(guò)復(fù)寫(xiě)base inner class的方法,來(lái)實(shí)現(xiàn)多態(tài)。 參見(jiàn)例BigEgg2.

//: innerclasses/BigEgg2.java   // Proper inheritance of an inner class.   import static net.mindview.util.Print.*;   class Egg2 {       protected class Yolk {         public Yolk() { print("Egg2.Yolk()"); }         public void f() { print("Egg2.Yolk.f()");}   }       private Yolk y = new Yolk();       public Egg2() { print("New Egg2()"); }       public void insertYolk(Yolk yy) { y = yy; }       public void g() { y.f(); }   }   public class BigEgg2 extends Egg2 {       public class Yolk extends Egg2.Yolk {           public Yolk() { print("BigEgg2.Yolk()"); }           public void f() { print("BigEgg2.Yolk.f()"); }   }       public BigEgg2() { insertYolk(new Yolk()); }       public static void main(String[] args) {           Egg2 e2 = new BigEgg2();           e2.g();   }   } /* Output:   Egg2.Yolk()   New Egg2()   Egg2.Yolk()   BigEgg2.Yolk()   BigEgg2.Yolk.f()   *///:~

局部?jī)?nèi)部類

局部?jī)?nèi)部類(local inner class)不能有訪問(wèn)限定符;有訪問(wèn)局部final變量和outer class所有類的權(quán)限;可以有命名的構(gòu)造器;在方法外不能訪問(wèn)。

絕大部分情況下,可以用匿名類來(lái)替代局部?jī)?nèi)部類,除非:

1. 需要命名的構(gòu)造器,或者需要重載構(gòu)造器

2. 需要多個(gè)內(nèi)部類的對(duì)象

此時(shí)就要用Local Inner class。

關(guān)于怎么理解Java編程中的內(nèi)部類問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI