<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    walterwing  
    日歷
    <2008年7月>
    293012345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789
    統(tǒng)計(jì)
    • 隨筆 - 12
    • 文章 - 1
    • 評論 - 7
    • 引用 - 0

    導(dǎo)航

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

     

     

    內(nèi)部類的概念與使用實(shí)在是有些繁雜,因?yàn)樗旧砩婕暗絡(luò)ava內(nèi)部一些很基礎(chǔ)的知識,包括修飾符、作用域等等,在網(wǎng)上很難搜索到一篇全面、準(zhǔn)確的關(guān)于內(nèi)部類的總結(jié),所以在這里拋磚引玉一下,希望能對自己、對大家都有所幫助。

    本篇大概分成三部分內(nèi)容,第一部分是對內(nèi)部類概念性的介紹,第二部分是對內(nèi)部類語法規(guī)則和特性方面的介紹,而第三部分則是對內(nèi)部類用法、用途的簡單介紹,第三部分的內(nèi)容主要參考自《Effective Java 2nd. Edition》中的Item 22: Favor static member classes over nonstatic


     

    一. 概念介紹

    1. 什么是內(nèi)部類

    簡單的說,內(nèi)部(inner)類指那些類定義代碼被置于其它類定義中的類;而對于一般的、類定義代碼不嵌套在其它類定義中的類,稱為頂層(top-level)類。對于一個(gè)內(nèi)部類,包含其定義代碼的類稱為它的外部(outer)類。

    2. 內(nèi)部類都有哪幾種

    一般來講,都是把內(nèi)部類分為四種:靜態(tài)成員類(static member classes)、非靜態(tài)成員類(nonstatic member classes)、局部類(local classes)、匿名類(anonymous classes)

    2.1. 靜態(tài)成員類:所謂靜態(tài)成員類,就是用static來修飾的,定義于外部類頂層的內(nèi)部類

    例:

    package test;

    public class OuterClass {
        
    // 可以在外部類頂層定義靜態(tài)成員類
        public static class Inner1 {
            
        }

        
        
    }



    2.2. 非靜態(tài)成員類:顧名思義,就是沒有用static來修飾的,定義于外部類頂層的內(nèi)部類

    例:
    package test;

    public class OuterClass {
        
    // 可以在外部類頂層定義非靜態(tài)成員類
        public class Inner1 {
            
        }

    }




    2.3. 局部類:定義于外部類的代碼塊或方法內(nèi)部的內(nèi)部類。局部類還可以進(jìn)一步細(xì)分為兩種:

        2.3.1. 局部靜態(tài)成員類:定義于外部類的靜態(tài)方法或靜態(tài)初始化代碼段中的局部類
        2.3.2. 局部成員類:定義于外部類的實(shí)例方法或?qū)嵗跏蓟a段中的局部類

    例:

    package test;

    public class OuterClass {
        
        
    public static void method1() {
            
    // 局部靜態(tài)成員類
            class inner4 {
                
            }

        }

        
        
    public void method2() {
            
    // 局部成員類
            class inner5 {
                
            }

        }

        
    }



        也就是說,局部類也有“靜態(tài)”和“非靜態(tài)”之分,取決于他所處的方法或代碼段。

    2.4. 匿名類:表面上來看,匿名類就是沒有類名的局部類。但其實(shí)二者還是有區(qū)別的。局部類,是創(chuàng)建一個(gè)新的類;而匿名類,是針對已經(jīng)定義好的接口或類,將其實(shí)現(xiàn)(接口)或擴(kuò)展(類)并實(shí)例化。

    例:

    package test;

    public class OuterClass {
            
        
    public static void method1() {
                    
            
    // 繼承OuterClass類,加入一個(gè)新的方法print(),然后實(shí)例化并調(diào)用print()方法
            new OuterClass() {
                
    public void print() {System.out.println("hi");}
            }
    .print();
        }

        
        
    public static void main(String[] args) {
            
    // 運(yùn)行結(jié)果:hi
            OuterClass.method1();
        }

    }


    注:繼承自某個(gè)類的匿名類,和實(shí)現(xiàn)某個(gè)接口的匿名類,在表現(xiàn)形式上略有差別:

    2.4.1 繼承自某個(gè)類的匿名類:

    new class-name ( [ argument-list ] ) { class-body }







        







    創(chuàng)建匿名類的示例時(shí),argument-list(如果有的話)將作為參數(shù)被傳入基類對應(yīng)的構(gòu)造函數(shù)























    2.4.2. 實(shí)現(xiàn)某接口的匿名類:

    new interface-name () { class-body }










    二. 語法規(guī)則

    1. 靜態(tài)成員類:

    1.1. 可以做的:

    像靜態(tài)方法或靜態(tài)字段一樣,可以用public, private, protected來修飾,不加則為默認(rèn)(package)
    可以訪問外部類的任一靜態(tài)字段或靜態(tài)方法
    可以用OuterClass.InnerClass的方式來引用

    1.2. 不可以做的:

    像外部類的靜態(tài)方法一樣,不可以訪問外部類的非靜態(tài)方法或非靜態(tài)字段

    2. 非靜態(tài)成員類:

    2.1. 可以做的:

    可以用public, private, protected來修飾,不加則為默認(rèn)(package)
    可以訪問外部類的任一字段和函數(shù)(不管是否static),這是因?yàn)榉庆o態(tài)成員類的實(shí)例包含外部類的引用。
    當(dāng)非靜態(tài)內(nèi)部類中所定義的某個(gè)成員變量和外部類中的變量重名時(shí),外部類的變量將被屏蔽,此時(shí)可以用OuterClass.this.來得到被屏蔽的外部類變量
    有兩種方式來創(chuàng)建非靜態(tài)成員類的實(shí)例。第一種比較常用,就是在外部類的方法內(nèi)部直接創(chuàng)建: InnerClass inner = new InnerClass(); 另外一種則是通過表達(dá)式enclosingInstance.new MemberClass(args)來創(chuàng)建。具體見2.2.

    2.2. 不可以做的:

    不能在非靜態(tài)成員類內(nèi)部定義static字段、方法或內(nèi)部類。這是因?yàn)橥耆梢詫⑦@些東西移到外部類中去;但是可以定義static final常量
    在第三方類里面(指非外部類的某個(gè)其他類)不可以用OuterClass.InnerClass inner = new OuterClass.InnerClass(); 的方法來創(chuàng)建非靜態(tài)成員類的實(shí)例。這是因?yàn)榉庆o態(tài)成員類實(shí)例是依賴于外部類實(shí)例而存在的(包含外部類的引用),但如果我們有了一個(gè)外部類的實(shí)例outerClass,則可以用下面的方法來創(chuàng)建:

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


    3. 局部類:

    3.1. 可以做的:

    能且只能訪問所屬代碼段中聲明為final的變量。這是因?yàn)榫植孔兞吭谄渌鶎俚拇a段(譬如某個(gè)函數(shù))執(zhí)行完畢后就會被回收,而一個(gè)局部類的實(shí)例卻可以在其類定義所屬代碼段執(zhí)行完畢后依然存在,如果它可操控非final的局部變量,用戶就可以通過該實(shí)例修改已不存在的局部變量,無意義。
    能且只能被final, abstract修飾

    3.2. 不可以做的:

    不能被public, private, protected修飾,也不能被static修飾。這是因?yàn)榫植款愔辉诙x它的代碼段中可見,不能在它所屬代碼段之外的代碼中使用
    同理,局部類內(nèi)部不能定義static成員
    不能以局部類形式定義一個(gè)接口。因?yàn)榫植款愔辉谄渌鶎俅a段中可見,定義這樣的接口無意義

    4.匿名類

    當(dāng)前僅當(dāng)匿名類處于非靜態(tài)代碼段時(shí),他會有外部類的引用(即可以訪問外部類任意資源)。局部類也是如此,不同的是匿名類在聲明處的同時(shí)被初始化。

    匿名類還有一個(gè)限制,就是不能同時(shí)實(shí)現(xiàn)多個(gè)接口,也不能同時(shí)實(shí)現(xiàn)一個(gè)接口并擴(kuò)展一個(gè)基類。這是因?yàn)槟涿惖穆暶骱蛯?shí)例化是同時(shí)發(fā)生的,它不像通常的類的聲明那樣,可以通過implement關(guān)鍵字指定多個(gè)接口,或者通過exteds關(guān)鍵字來指定基類。對一個(gè)匿名類而言,他只能通過指定接口或基類的名字,來告訴編譯器說:現(xiàn)在我要實(shí)現(xiàn)這個(gè)接口(or擴(kuò)展這個(gè)基類),因此一個(gè)匿名類能且只能實(shí)現(xiàn)一個(gè)接口或者擴(kuò)展一個(gè)基類





    三. 內(nèi)部類的使用及其意義

    1. 靜態(tài)成員類

    靜態(tài)成員類的通常用法是作為一個(gè)public helper class,與他的OuterClass結(jié)合在一起使用,為OuterClass服務(wù)。
    比如一個(gè)Calculator類,他有各種操作,這些操作就可以存儲在他的靜態(tài)內(nèi)部類Operation里,客戶端就可以通過Calculator.Operation.PLUS或者Calculator.Operation.MINUS等來指定各種操作

    那一個(gè)private的靜態(tài)成員類可以用來干什么呢?可以用來代表外部類所需要的某個(gè)組件。
    比如,對于Map接口,他內(nèi)部就有一個(gè)Entry類,一個(gè)Entry對象對應(yīng)著一個(gè)鍵-值對,該對象上的方法(getKey, getValue, setValue)也不需要訪問外部類的資源,將Entry定義為private的靜態(tài)成員類類就是最合適的。

    2. 非靜態(tài)成員類

    一種通常的用法是把非靜態(tài)成員類作為一個(gè)Adapter,使外部類的實(shí)例看起來提供了某個(gè)不相關(guān)的類的實(shí)例的功能。
    比如,collection接口的各種實(shí)現(xiàn)類,一般就是用非靜態(tài)成員類來實(shí)現(xiàn)他們的iterator:
    public class MySet<E> extends AbstractSet<E> {
        
    public Iterator<E> iterator() {
            
    return new MyIterator();
        }

        
    private class MyIterator implements Iterator<E> {
        }

    }

    關(guān)于靜態(tài)成員類和非靜態(tài)成員類,有一點(diǎn)需要注意的是:如果你的內(nèi)部類不需要訪問外部類的成員變量和函數(shù)(尤其是指非static類型的),那么盡量用靜態(tài)成員類。為什么?因?yàn)槊總€(gè)非靜態(tài)成員類的實(shí)例都將保存他的外部類的引用,這不僅造成時(shí)空上的浪費(fèi),而且可能導(dǎo)致當(dāng)外部類實(shí)際上已經(jīng)可以被垃圾回收器回收的時(shí)候,卻因?yàn)槟硞€(gè)非靜態(tài)成員類實(shí)例還保留著該外部類的引用而不能回收該外部類。

    3. 匿名類

    匿名類用的地方應(yīng)該是這四種內(nèi)部類中最多的,至少我是這樣。我經(jīng)常用匿名類的地方就是在事件響應(yīng)的代碼中。
    Effective Java中總結(jié)了三種匿名類的用途:
    3.1. To create function objects on the fly
    3.2. To create process objects, such as Runnable, Thread, TimerTask instances
    3.3. To use within static factory methods


    總結(jié),
    1.當(dāng)內(nèi)部類需要在方法外部仍然可見時(shí),使用成員類(靜態(tài)or非靜態(tài));當(dāng)內(nèi)部類比較長,放在方法內(nèi)部會影響程序可讀性時(shí),使用成員類(靜態(tài)or非靜態(tài));
    2. 如果需要在內(nèi)部類內(nèi)部定義靜態(tài)成員,只能使用靜態(tài)成員類(其他三個(gè)都不支持);如果成員類的每個(gè)實(shí)例都需要外部類的引用,定義為非靜態(tài)的,否則,就要定義成靜態(tài)的;
    3. 假設(shè)我們需要在方法內(nèi)部定義一個(gè)局部類或者匿名類,如果我們只需要在這一個(gè)位置使用內(nèi)部類實(shí)例,并且已經(jīng)有預(yù)先定義好的基類或接口,那就使用匿名類;否則,使用局部類
    posted on 2008-07-01 20:04 This is Wing 閱讀(247) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
     
    Copyright © This is Wing Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 亚洲高清美女一区二区三区| 亚洲人成欧美中文字幕| 成人黄色免费网址| 自拍偷区亚洲国内自拍| 四虎影视在线永久免费看黄 | 国内永久免费crm系统z在线| 亚洲日本中文字幕| 在线观看人成视频免费| 五月天婷婷免费视频| 亚洲午夜未满十八勿入| 国产免费卡一卡三卡乱码| 一区二区三区无码视频免费福利| 亚洲午夜电影一区二区三区| 亚洲国产精品成人网址天堂| **aaaaa毛片免费同男同女| 国产精品成人亚洲| 亚洲精品视频观看| 亚洲日本韩国在线| 野花高清在线电影观看免费视频 | 最新国产乱人伦偷精品免费网站| 亚洲熟女乱色一区二区三区| 亚洲Av永久无码精品三区在线 | 日本人成在线视频免费播放| 国产成人人综合亚洲欧美丁香花 | 国产亚洲人成无码网在线观看| 性色av无码免费一区二区三区| 99re6在线视频精品免费| 爱爱帝国亚洲一区二区三区| 亚洲丝袜美腿视频| 亚洲无码视频在线| 成人黄页网站免费观看大全| 久9热免费精品视频在线观看| 精品女同一区二区三区免费播放| 亚洲午夜成激人情在线影院| 国产亚洲成av片在线观看 | 亚洲欧洲国产精品香蕉网| 好爽…又高潮了毛片免费看 | 国产亚洲情侣一区二区无码AV| 国内精品乱码卡1卡2卡3免费| 十八禁在线观看视频播放免费| 国产亚洲美女精品久久久久|