Effective Java讀書筆記八:巢狀類(22)

衣舞晨風發表於2017-02-08

巢狀類(nested class)是指被定義在另一個類的內部的類。巢狀類存在的目的應該是為它的外圍類(enclosing class)提供服務。如果巢狀類將來可能會用於其他的某個環境中,它就應該是頂層類(top-level class)。

巢狀類有四種:靜態成員類(static member class)、非靜態成員類(nonstatic member class)、匿名類(anonymous class)和區域性類(local class)。除了第一種之外,其他三種都被稱為內部類(inner class)。

靜態成員類是最簡單的一種巢狀類。最好把它看作是普通的類,只是碰巧被宣告在另一個類的內部而已,它可以訪問外圍類的所有成員,包括那些宣告為私有的成員。靜態成員類是外圍類的一個靜態成員,與其他的靜態成員一樣,也遵守同樣的可訪問性規則。如果它被宣告為私有的,它就只能在外圍類的內部才可以被訪問,等等。

靜態成員類的一種常見用是作為公有的輔助類,僅當與它的外部類一起使用時才有意義。例如,考慮一個列舉,它描述了計算器支援的各種操作。Operation列舉應該是Calculator類的公有靜態成員類,然後,Calculator類的客戶端就可以用諸如Calculator.Operation.PLUS和Calculator.Operation.MINUS這樣的名稱來引用這些操作。

從語法上講,靜態成員類和非靜態成員類之間唯一的區別是,靜態成員類的宣告中包含了修飾符static。儘管他們的語法非常的相似,但是這兩種巢狀類有很大的不同。非靜態成員類的每個示例都隱含著與外圍類的一個外圍例項(enclosing instance)相關聯。在非靜態成員類的例項方法內部,可以呼叫外圍例項上的方法,或者利用修飾過的this構造獲得外圍例項的引用。如果巢狀類的例項可以在外圍類的例項之外獨立存在,這個巢狀類就必須是靜態成員類:在沒有外圍例項的情況下,要想建立非靜態成員類的例項是不可能的。

當非靜態成員類的例項被建立的時候,它和外圍例項之間的關聯關係也隨之建立起來;而且,這種關聯關係以後也不能被修改。通常情況下,當在外圍類的某個例項方法的內部呼叫了非靜態成員類的構造器時,這種關聯就自動建立起來。這種關聯需要消耗非靜態成員類的例項空間,並且增加了構造的時間開銷。

非靜態成員類常見用法是定義一個Adapter,它允許外部類的例項被看作是另一個不相關的類的例項。

//Typical use of a nonstatic member class  
public class MySet<E> extends AbstractSet<E>  
{  
    public Iterator<E> iterator()  
    {  
        return new MyIterator();  
    }  

    private class MyIterator implements Iterator<E>  
    {  

    }  
}

如果宣告成員類不要求訪問外圍例項,就要始終把static修飾符放在它的生命中,使它成為靜態成員類,而不是非靜態成員類。如果省略了static修飾符,則每個例項都將包含一個額外的指向外圍物件的引用。儲存這份引用要消耗時間和空間,並且會導致外圍例項在符合垃圾回收時仍然得以保留。如果沒有外圍例項的情況下,也需要分配例項,就不能使用非靜態成員類,因為非靜態成員類的例項必須要有一個外圍例項。

私有靜態成員類的一種常見用法用來代表外圍類所代表的物件的元件。

匿名類不同於Java程式設計語言中的其他任何語法單元。正如你所想象的,匿名類沒有名字。它不是外圍類的一個成員。它並不與其他的成員一起被宣告,而是在使用的同時被宣告和例項化。匿名類可以出現在程式碼中任何允許存在表示式的地方。當且僅當匿名類出現在非靜態的環境中時,它才有外圍例項。但是即使它們出現在靜態的環境中,也不可能擁有任何靜態成員。

區域性類是四種巢狀類中用的最少的類。在任何“可以宣告區域性變數”的地方,都可以宣告區域性類,並且區域性類也遵守同樣的作用域規則。區域性類與其他三種巢狀類中的每一種都有一些共同的屬性。與成員類一樣,區域性類有名字,可以被重複使用。與匿名類一樣,只有當區域性類實在非靜態環境中定義的時候,才有外圍例項,它們也不能包含靜態成員。與匿名類一樣,它們必須簡短以便不會影響到可讀性。

如果一個巢狀類需要在單個方法之外仍然可見的,或者它太長了,不適合於放在方法內部,就應該使用成員類。如果成員類的每個示例都需要一個指向外圍例項的引用,就要把成員類做成非靜態的;否則,就做成靜態的。假設這個巢狀類屬於一個方法的內部,如果你只需要在一個地方建立例項,並且已經有了一個預置的型別可以說明這個類的特徵,就要把它做成匿名類;否則,就做成區域性類。

《Effective Java中文版 第2版》PDF版下載:
http://download.csdn.net/detail/xunzaosiyecao/9745699

作者:jiankunking 出處:http://blog.csdn.net/jiankunking

相關文章