1. 程式人生 > >Java中的巢狀類總結

Java中的巢狀類總結

一直對內部類、靜態內部類這些名詞的認識不太清晰,做一些小小的總結。
一、什麼是巢狀類(nested class)?
首先Java中的巢狀類(nested class)是指定義在另一個類的內部的類,所以叫巢狀類。它有很多種分類的方式,從型別上分,有成員類(member class)、匿名類(anonymous class)和區域性類(local class);從屬性上來說,有靜態類(static class)和內部類(inner class)之分,除了靜態成員類之外,其他的非靜態成員類、匿名類和區域性類都可以說是內部類。下面我們來了解每種型別的特點和作用。

二、成員類(member class)
成員類是我們用的比較常見的一種型別,就是在一個類的內部(類的結構體內)定義的類,而成員類又分為靜態成員類(static member class)和內部成員類(inner member class)、也就是非靜態成員類。
1、靜態成員類(static member class)
靜態成員類就是定義在類的內部的,用static修飾符修飾的類,是最簡單的巢狀類。可以這麼來理解,它就是一個普通的類,只不過恰巧被宣告在另一個類的內部用作輔助而已,而你將它宣告在類的外部不是不可以,只是宣告在內部更能看出它“輔助”外部類的作用罷了。由於是static修飾的,它不能訪問外部類的非static屬性和方法,但它可以單獨建立,就是在不需要外部類的例項的情況下可以建立,比如Builder模式中的內部類Builder類就必須是static的,為什麼呢?因為Builder是要建立外部類例項的輔助類,是獨立存在的,它的職責是建立外部類的例項,所以它必須是static的。至於為什麼這麼說,在區別裡我會說明的。
2、內部成員類(inner member class)
內部成員類也叫非靜態成員類,就是沒有static修飾的寫在外部類結構體內的類。內部成員類最關鍵的一個特點就是它具有一個隱含的外部類的例項,所以說內部成員類和它的外部類至少是一對一的關係,一個外部類例項對應著至少一個內部類例項,沒有外部類例項是建立不了內部類例項的!內部成員類可以訪問外部類的所有方法和屬性,這是與靜態成員類行為上的區別。它的常見用法就是表示外圍類所代表的物件的一個元件,比如Set的元件之一迭代器Iterator。
3、區別
靜態成員類和非靜態成員類有什麼至關重要的區別呢?我們為什麼要分靜態和非靜態呢?其實最重要的原因就是外圍例項(enclosing instance)的區別,非靜態成員類的例項中隱含著一個外部類的例項,也就是說,非靜態成員類是“依附”於外部類的,需要外部類的例項才能有自己的例項,而靜態成員類的static就表示了它的獨立性,它只是與外部類相關,而不與它的某個例項相關。比如一個策略Host釋出自己的靜態比較器例項,如果比較器是內部實現的,那它必然是一個靜態內部類,因為它與你的Host例項沒有關係,是與Host類相關的。而且編輯器也告訴了我麼你這一點,類的靜態屬性的型別不能是內部成員類,必須是靜態成員類!(仔細思考一下,原因就是static屬性不能提供一個隱含的外部類例項)

三、匿名類(anonymous class)
匿名類也是內部類之一哦,我們應該時刻清楚內部類與靜態類的區別。匿名類是Java的特性之一,在宣告新的物件的同時宣告類,即同時宣告和例項化,並且不能再次使用,所以才“匿名”。同樣,作為內部類,匿名類也會具有外部類的具體例項,這個是很需要注意的問題(記憶體洩漏方面,如果你儲存了一個長期存在的內部類例項,它具有你外部類例項的隱含例項,那麼即使你的外部類已經應該拋棄了,但由於它的引用仍然存在,它就不能被回收)。另外我們要注意,匿名類是可以存在在靜態環境中,它不會擁有外部例項,但也不能擁有任何靜態成員。
匿名類就是一個簡潔的“一次性”類的實現方式,但要儘量保持簡潔,比如android中的button點選監聽經常遇到的程式碼:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //具體實現
            }
        });

這是一種簡潔的方式,但一旦內部實現變多,就會增大程式碼的閱讀難度,就應該採取別的實現方式了。
《Effective Java》中總結的匿名類的作用有主要三種:1、動態常見函式物件(function object);2、主要是用於建立過程物件,比如Runnable、Thread例項等;3、用於靜態工廠方法的內部。在我看來其實可以用更抽象的方式來表達:
1、當內部類只在一個函式中作為引數使用一次(函式物件就是典型);
2、當內部類作為過程物件使用(Runnable就是過程物件);
3、當內部類只當做例項在函式中直接返回(靜態工廠返回例項)

四、區域性類(local class)
區域性類是用的非常少的類,它也是內部類之一,一般出現在函式體的內部,其實只要是“可以宣告區域性變數”的地方,都可以宣告區域性類,並且作用域規則和區域性變數一樣,除了可以重複使用,其他特點和匿名類一樣。

如果覺得我的文章裡有任何錯誤,歡迎評論指正!如果覺得寫得好也歡迎大家留言或者點贊,一起進步、一起學習!