什么是內(nèi)部類瞎领?內(nèi)部類的作用及分類

內(nèi)部類我們從外面看是非常容易理解的怔蚌,無非就是在一個(gè)類的內(nèi)部在定義一個(gè)類别厘。

public class OuterClass {

? ? private String name ;

? ? private int age;

? ? public String getName() {

? ? ? ? return name;

? ? }

? ? public void setName(String name) {

? ? ? ? this.name = name;

? ? }

? ? public int getAge() {

? ? ? ? return age;

? ? }

? ? public void setAge(int age) {

? ? ? ? this.age = age;

? ? }


? ? class InnerClass{

? ? ? ? public InnerClass(){

? ? ? ? ? ? name = "chenssy";

? ? ? ? ? ? age = 23;

? ? ? ? }

? ? }

}

?在這里InnerClass就是內(nèi)部類怎棱,對于初學(xué)者來說內(nèi)部類實(shí)在是使用的不多哩俭,鄙人菜鳥一個(gè)同樣沒有怎么使用過(貌似僅僅只在做swing 注冊事件中使用過),但是隨著編程能力的提高拳恋,我們會領(lǐng)悟到它的魅力所在凡资,它可以使用能夠更加優(yōu)雅的設(shè)計(jì)我們的程序結(jié)構(gòu)。在使用內(nèi)部類之間我們需要明白為什么要使用內(nèi)部類谬运,內(nèi)部類能夠?yàn)槲覀儙硎裁礃拥暮锰?/p>

一隙赁、為什么要使用內(nèi)部類

為什么要使用內(nèi)部類?在《Think in java》中有這樣一句話:使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn)梆暖,所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn)伞访,對于內(nèi)部類都沒有影響。

在我們程序設(shè)計(jì)中有時(shí)候會存在一些使用接口很難解決的問題轰驳,這個(gè)時(shí)候我們可以利用內(nèi)部類提供的厚掷、可以繼承多個(gè)具體的或者抽象的類的能力來解決這些程序設(shè)計(jì)問題〖督猓可以這樣說蝗肪,接口只是解決了部分問題,而內(nèi)部類使得多重繼承的解決方案變得更加完整蠕趁。

public interface Father {

}

public interface Mother {

}

public class Son implements Father, Mother {

}

public class Daughter implements Father{

? ? class Mother_ implements Mother{


? ? }

}

其實(shí)對于這個(gè)實(shí)例我們確實(shí)是看不出來使用內(nèi)部類存在何種優(yōu)點(diǎn)薛闪,但是如果Father、Mother不是接口俺陋,而是抽象類或者具體類呢豁延?這個(gè)時(shí)候我們就只能使用內(nèi)部類才能實(shí)現(xiàn)多重繼承了。

????? 其實(shí)使用內(nèi)部類最大的優(yōu)點(diǎn)就在于它能夠非常好的解決多重繼承的問題腊状,但是如果我們不需要解決多重繼承問題诱咏,那么我們自然可以使用其他的編碼方式,但是使用內(nèi)部類還能夠?yàn)槲覀儙砣缦绿匦裕ㄕ浴禩hink in java》):

?? 1缴挖、內(nèi)部類可以用多個(gè)實(shí)例袋狞,每個(gè)實(shí)例都有自己的狀態(tài)信息,并且與其他外圍對象的信息相互獨(dú)立映屋。

?2苟鸯、在單個(gè)外圍類中,可以讓多個(gè)內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口棚点,或者繼承同一個(gè)類早处。

?3、創(chuàng)建內(nèi)部類對象的時(shí)刻并不依賴于外圍類對象的創(chuàng)建瘫析。

?4砌梆、內(nèi)部類并沒有令人迷惑的“is-a”關(guān)系默责,他就是一個(gè)獨(dú)立的實(shí)體。

?5咸包、內(nèi)部類提供了更好的封裝桃序,除了該外圍類,其他類都不能訪問烂瘫。

二媒熊、內(nèi)部類基礎(chǔ)

在這個(gè)部分主要介紹內(nèi)部類如何使用外部類的屬性和方法,以及使用.this與.new忱反。

????? 當(dāng)我們在創(chuàng)建一個(gè)內(nèi)部類的時(shí)候,它無形中就與外圍類有了一種聯(lián)系滤愕,依賴于這種聯(lián)系温算,它可以無限制地訪問外圍類的元素。

public class OuterClass {

? ? private String name ;

? ? private int age;

? ? /**省略getter和setter方法**/


? ? public class InnerClass{

? ? ? ? public InnerClass(){

? ? ? ? ? ? name = "chenssy";

? ? ? ? ? ? age = 23;

? ? ? ? }


? ? ? ? public void display(){

? ? ? ? ? ? System.out.println("name:" + getName() +"? ;age:" + getAge());

? ? ? ? }

? ? }


? ? public static void main(String[] args) {

? ? ? ? OuterClass outerClass = new OuterClass();

? ? ? ? OuterClass.InnerClass innerClass = outerClass.new InnerClass();

? ? ? ? innerClass.display();

? ? }

}

在這個(gè)應(yīng)用程序中间影,我們可以看到內(nèi)部了InnerClass可以對外圍類OuterClass的屬性進(jìn)行無縫的訪問注竿,盡管它是private修飾的。這是因?yàn)楫?dāng)我們在創(chuàng)建某個(gè)外圍類的內(nèi)部類對象時(shí)魂贬,此時(shí)內(nèi)部類對象必定會捕獲一個(gè)指向那個(gè)外圍類對象的引用巩割,只要我們在訪問外圍類的成員時(shí),就會用這個(gè)引用來選擇外圍類的成員付燥。

????? 其實(shí)在這個(gè)應(yīng)用程序中我們還看到了如何來引用內(nèi)部類:引用內(nèi)部類我們需要指明這個(gè)對象的類型:OuterClasName.InnerClassName宣谈。同時(shí)如果我們需要?jiǎng)?chuàng)建某個(gè)內(nèi)部類對象,必須要利用外部類的對象通過.new來創(chuàng)建內(nèi)部類:OuterClass.InnerClass innerClass = outerClass.new InnerClass();键科。

????? 同時(shí)如果我們需要生成對外部類對象的引用闻丑,可以使用OuterClassName.this,這樣就能夠產(chǎn)生一個(gè)正確引用外部類的引用了勋颖。當(dāng)然這點(diǎn)實(shí)在編譯期就知曉了嗦嗡,沒有任何運(yùn)行時(shí)的成本。

public class OuterClass {

? ? public void display(){

? ? ? ? System.out.println("OuterClass...");

? ? }


? ? public class InnerClass{

? ? ? ? public OuterClass getOuterClass(){

? ? ? ? ? ? return OuterClass.this;

? ? ? ? }

? ? }


? ? public static void main(String[] args) {

? ? ? ? OuterClass outerClass = new OuterClass();

? ? ? ? OuterClass.InnerClass innerClass = outerClass.new InnerClass();

? ? ? ? innerClass.getOuterClass().display();

? ? }

}

到這里了我們需要明確一點(diǎn)饭玲,內(nèi)部類是個(gè)編譯時(shí)的概念侥祭,一旦編譯成功后,它就與外圍類屬于兩個(gè)完全不同的類(當(dāng)然他們之間還是有聯(lián)系的)茄厘。對于一個(gè)名為OuterClass的外圍類和一個(gè)名為InnerClass的內(nèi)部類矮冬,在編譯成功后,會出現(xiàn)這樣兩個(gè)class文件:OuterClass.class和OuterClass$InnerClass.class次哈。

????? 在Java中內(nèi)部類主要分為成員內(nèi)部類欢伏、局部內(nèi)部類、匿名內(nèi)部類亿乳、靜態(tài)內(nèi)部類硝拧。

三径筏、成員內(nèi)部類

成員內(nèi)部類也是最普通的內(nèi)部類,它是外圍類的一個(gè)成員障陶,所以他是可以無限制的訪問外圍類的所有 成員屬性和方法滋恬,盡管是private的,但是外圍類要訪問內(nèi)部類的成員屬性和方法則需要通過內(nèi)部類實(shí)例來訪問抱究。

在成員內(nèi)部類中要注意兩點(diǎn)恢氯,第一:成員內(nèi)部類中不能存在任何static的變量和方法;第二:成員內(nèi)部類是依附于外圍類的鼓寺,所以只有先創(chuàng)建了外圍類才能夠創(chuàng)建內(nèi)部類勋拟。

public class OuterClass {

? ? private String str;


? ? public void outerDisplay(){

? ? ? ? System.out.println("outerClass...");

? ? }


? ? public class InnerClass{

? ? ? ? public void innerDisplay(){

? ? ? ? ? ? //使用外圍內(nèi)的屬性

? ? ? ? ? ? str = "chenssy...";

? ? ? ? ? ? System.out.println(str);

? ? ? ? ? ? //使用外圍內(nèi)的方法

? ? ? ? ? ? outerDisplay();

? ? ? ? }

? ? }


? ? /*推薦使用getxxx()來獲取成員內(nèi)部類,尤其是該內(nèi)部類的構(gòu)造函數(shù)無參數(shù)時(shí) */

? ? public InnerClass getInnerClass(){

? ? ? ? return new InnerClass();

? ? }


? ? public static void main(String[] args) {

? ? ? ? OuterClass outer = new OuterClass();

? ? ? ? OuterClass.InnerClass inner = outer.getInnerClass();

? ? ? ? inner.innerDisplay();

? ? }

}

四妈候、局部內(nèi)部類

有這樣一種內(nèi)部類敢靡,它是嵌套在方法和作用于內(nèi)的,對于這個(gè)類的使用主要是應(yīng)用與解決比較復(fù)雜的問題苦银,想創(chuàng)建一個(gè)類來輔助我們的解決方案啸胧,到那時(shí)又不希望這個(gè)類是公共可用的,所以就產(chǎn)生了局部內(nèi)部類幔虏,局部內(nèi)部類和成員內(nèi)部類一樣被編譯纺念,只是它的作用域發(fā)生了改變,它只能在該方法和屬性中被使用想括,出了該方法和屬性就會失效陷谱。

????? 對于局部內(nèi)部類實(shí)在是想不出什么好例子,所以就引用《Think in java》中的經(jīng)典例子了瑟蜈。

????? 定義在方法里:

public class Parcel5 {

? ? public Destionation destionation(String str){

? ? ? ? class PDestionation implements Destionation{

? ? ? ? ? ? private String label;

? ? ? ? ? ? private PDestionation(String whereTo){

? ? ? ? ? ? ? ? label = whereTo;

? ? ? ? ? ? }

? ? ? ? ? ? public String readLabel(){

? ? ? ? ? ? ? ? return label;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return new PDestionation(str);

? ? }


? ? public static void main(String[] args) {

? ? ? ? Parcel5 parcel5 = new Parcel5();

? ? ? ? Destionation d = parcel5.destionation("chenssy");

? ? }

}

定義在作用域內(nèi):

public class Parcel6 {

? ? private void internalTracking(boolean b){

? ? ? ? if(b){

? ? ? ? ? ? class TrackingSlip{

? ? ? ? ? ? ? ? private String id;

? ? ? ? ? ? ? ? TrackingSlip(String s) {

? ? ? ? ? ? ? ? ? ? id = s;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? String getSlip(){

? ? ? ? ? ? ? ? ? ? return id;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? TrackingSlip ts = new TrackingSlip("chenssy");

? ? ? ? ? ? String string = ts.getSlip();

? ? ? ? }

? ? }


? ? public void track(){

? ? ? ? internalTracking(true);

? ? }


? ? public static void main(String[] args) {

? ? ? ? Parcel6 parcel6 = new Parcel6();

? ? ? ? parcel6.track();

? ? }

}

五叭首、匿名內(nèi)部類

我們經(jīng)常使用這種方式來綁定事件
button2.addActionListener(

? ? ? ? ? ? ? ? new ActionListener(){?

? ? ? ? ? ? ? ? ? ? public void actionPerformed(ActionEvent e) {?

? ? ? ? ? ? ? ? ? ? ? ? System.out.println("你按了按鈕二");?

? ? ? ? ? ? ? ? ? ? }?

? ? ? ? ? ? ? ? });

這里我們就需要看清幾個(gè)地方

?1、?匿名內(nèi)部類是沒有訪問修飾符的踪栋。

?? 2焙格、?new 匿名內(nèi)部類,這個(gè)類首先是要存在的夷都。如果我們將那個(gè)InnerClass接口注釋掉眷唉,就會出現(xiàn)編譯出錯(cuò)。

?3囤官、?注意getInnerClass()方法的形參冬阳,第一個(gè)形參是用final修飾的,而第二個(gè)卻沒有党饮。同時(shí)我們也發(fā)現(xiàn)第二個(gè)形參在匿名內(nèi)部類中沒有使用過肝陪,所以當(dāng)所在方法的形參需要被匿名內(nèi)部類使用,那么這個(gè)形參就必須為final刑顺。

?4氯窍、?匿名內(nèi)部類是沒有構(gòu)造方法的饲常。因?yàn)樗B名字都沒有何來構(gòu)造方法。

六狼讨、靜態(tài)內(nèi)部類

在java提高篇-----關(guān)鍵字static中提到Static可以修飾成員變量贝淤、方法、代碼塊政供,其他它還可以修飾內(nèi)部類播聪,使用static修飾的內(nèi)部類我們稱之為靜態(tài)內(nèi)部類,不過我們更喜歡稱之為嵌套內(nèi)部類布隔。靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個(gè)最大的區(qū)別离陶,我們知道非靜態(tài)內(nèi)部類在編譯完成之后會隱含地保存著一個(gè)引用,該引用是指向創(chuàng)建它的外圍內(nèi)衅檀,但是靜態(tài)內(nèi)部類卻沒有招刨。沒有這個(gè)引用就意味著:

?1、?它的創(chuàng)建是不需要依賴于外圍類的术吝。

?2计济、?它不能使用任何外圍類的非static成員變量和方法茸苇。

public class OuterClass {

? ? private String sex;

? ? public static String name = "chenssy";


? ? /**

? ? *靜態(tài)內(nèi)部類

? ? */

? ? static class InnerClass1{

? ? ? ? /* 在靜態(tài)內(nèi)部類中可以存在靜態(tài)成員 */

? ? ? ? public static String _name1 = "chenssy_static";


? ? ? ? public void display(){

? ? ? ? ? ? /*

? ? ? ? ? ? * 靜態(tài)內(nèi)部類只能訪問外圍類的靜態(tài)成員變量和方法

? ? ? ? ? ? * 不能訪問外圍類的非靜態(tài)成員變量和方法

? ? ? ? ? ? */

? ? ? ? ? ? System.out.println("OutClass name :" + name);

? ? ? ? }

? ? }


? ? /**

? ? * 非靜態(tài)內(nèi)部類

? ? */

? ? class InnerClass2{

? ? ? ? /* 非靜態(tài)內(nèi)部類中不能存在靜態(tài)成員 */

? ? ? ? public String _name2 = "chenssy_inner";

? ? ? ? /* 非靜態(tài)內(nèi)部類中可以調(diào)用外圍類的任何成員,不管是靜態(tài)的還是非靜態(tài)的 */

? ? ? ? public void display(){

? ? ? ? ? ? System.out.println("OuterClass name:" + name);

? ? ? ? }

? ? }


? ? /**

? ? * @desc 外圍類方法

? ? * @author chenssy

? ? * @data 2013-10-25

? ? * @return void

? ? */

? ? public void display(){

? ? ? ? /* 外圍類訪問靜態(tài)內(nèi)部類:內(nèi)部類. */

? ? ? ? System.out.println(InnerClass1._name1);

? ? ? ? /* 靜態(tài)內(nèi)部類 可以直接創(chuàng)建實(shí)例不需要依賴于外圍類 */

? ? ? ? new InnerClass1().display();


? ? ? ? /* 非靜態(tài)內(nèi)部的創(chuàng)建需要依賴于外圍類 */

? ? ? ? OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();

? ? ? ? /* 方位非靜態(tài)內(nèi)部類的成員需要使用非靜態(tài)內(nèi)部類的實(shí)例 */

? ? ? ? System.out.println(inner2._name2);

? ? ? ? inner2.display();

? ? }


? ? public static void main(String[] args) {

? ? ? ? OuterClass outer = new OuterClass();

? ? ? ? outer.display();

? ? }

}

上面這個(gè)例子充分展現(xiàn)了靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的區(qū)別排苍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市学密,隨后出現(xiàn)的幾起案子淘衙,更是在濱河造成了極大的恐慌,老刑警劉巖腻暮,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤守,死亡現(xiàn)場離奇詭異,居然都是意外死亡哭靖,警方通過查閱死者的電腦和手機(jī)具垫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來试幽,“玉大人筝蚕,你說我怎么就攤上這事∑涛耄” “怎么了起宽?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長济榨。 經(jīng)常有香客問我坯沪,道長,這世上最難降的妖魔是什么擒滑? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任腐晾,我火速辦了婚禮叉弦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赴魁。我一直安慰自己卸奉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布颖御。 她就那樣靜靜地躺著榄棵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪潘拱。 梳的紋絲不亂的頭發(fā)上疹鳄,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音芦岂,去河邊找鬼瘪弓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛禽最,可吹牛的內(nèi)容都是我干的腺怯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼川无,長吁一口氣:“原來是場噩夢啊……” “哼呛占!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懦趋,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤晾虑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后仅叫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帜篇,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年诫咱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笙隙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坎缭,死狀恐怖竟痰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幻锁,我是刑警寧澤凯亮,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站哄尔,受9級特大地震影響假消,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岭接,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一富拗、第九天 我趴在偏房一處隱蔽的房頂上張望臼予。 院中可真熱鬧,春花似錦啃沪、人聲如沸粘拾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缰雇。三九已至,卻和暖如春追驴,著一層夾襖步出監(jiān)牢的瞬間械哟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工殿雪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留暇咆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓丙曙,卻偏偏與公主長得像爸业,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子亏镰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載:https://juejin.im/post/5a903ef96fb9a063435ef0c8 本文將會從以...
    福later閱讀 402評論 0 3
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用扯旷。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 4,587評論 1 114
  • DAY 05 1、 public classArrayDemo { public static void mai...
    周書達(dá)閱讀 662評論 0 0
  • 最近在設(shè)計(jì)公司的用戶體系拆挥。由于我們公司暫時(shí)有三個(gè)產(chǎn)品薄霜,不同類型某抓。每個(gè)類型都承載著完全不同業(yè)務(wù)領(lǐng)域纸兔。因此就需要考慮用...
    枯藤老叔閱讀 3,423評論 0 11
  • 1月23日,陰否副。 閱讀書目:《如何把事情做到最好》汉矿。 作者:美國作家喬治?倫納德 ,二戰(zhàn)期間學(xué)習(xí)駕駛戰(zhàn)斗機(jī)备禀,并留校...
    陳陳_19b4閱讀 327評論 0 1