讀《Effective java 中文版》(19)

2021-04-06 12:16:33 字數 2624 閱讀 2646

第18條:優先考慮靜態成員類

巢狀類(nested class)是指被定義在另一類的內部的類,它只為它的外圍類服務。如果乙個巢狀類可能會用於其它的某個環境,那就應為乙個頂層類(top-level class)。巢狀類有四種:靜態成員類(static member class)、非靜態成員類(nonstatic member class)、匿名類(anonymous class)和區域性類(local class),其中後三種稱為內部類(inner class)。

靜態成員類是一種最簡單的巢狀類,最後把它看作乙個普通的類,碰巧被宣告在另乙個類的內部而已,它可以訪問外圍類的所有成員,包括那些宣告為私有的成員。靜態成員類是外圍類的乙個靜態成員,與其他的靜態成員一樣,遵守同樣的可訪問性規則。如果它被宣告為私有的,則只能在外圍類的內部才可以被訪問。靜態成員類的一種通常用法是作為公有的輔助類,僅當它與它的外部類一起使用時才有意義。

從語法上,非靜態成員類與靜態成員類的差別在於後者有乙個static。非靜態成員類的每乙個例項,都隱含著與外圍類的乙個外圍例項緊密聯絡在一起。在非靜態成員類的例項方法內部,呼叫外圍例項上的方法是可能的,或者使用乙個經過修飾的this也可以得到個指向外圍例項的引用。在沒有外圍例項的情況下,要想建立非靜態成員類的例項是不可能的。非靜態成員類的一種通常用法是定義乙個adapter,它允許外部類的乙個例項被看作另乙個不相關的類的例項。如map介面的實現往往使用非靜態成員類來實現它們的「集合」檢視,這些「集合」檢視是由map的keyset、entryset、value方法返回。再看set集合介面實現迭代器的例子:

//typical use of a nonstatic member class

public class myset extends abstractset

private class myiterator implements iterator

}如果宣告的成員類不要求訪問外圍例項,那麼就把static修飾符放到成員類的宣告中。這會減少維護成員類例項對外圍例項物件的引用的開銷。

私有靜態成員類的一種通常用法是用來代表外圍類物件的元件。例如:map例項把一些key和value關聯起來,其內部通常有乙個entry物件對應於每個鍵值對。每個entry物件都與乙個map物件關聯,但entry的方法(getkey、getvalue、setvalue)都不需要外圍的map。此時,用私有的靜態成員類是最佳選擇。

匿名類沒有名字,它不是外圍類的乙個成員。它並不與其它的成員一起被宣告,而在被使用的點上同時宣告和被例項化。匿名類可以出現在**中任何允許表示式出現的地方。匿名類的行為與成員類非常類似,具體取決於它所在環境:如果匿名類出現在乙個非靜態的環境中,則它有乙個外圍例項。

匿名類的適用性有一些限制:

匿名類的常見用法:

匿名類的一通常用法是建立乙個函式物件(function object),如:

//typical use of an anonymous class

//arrays.sort(args,new comparator()

});另乙個常見用法是建立乙個過程物件(process object),如thread、runnable、timertasker例項。

在乙個靜態工廠方法的內部(參見第16條)

用在複雜的型別安全列舉型別(它要求為每個例項提供單獨的子類)

例子:

//typical use of a public static member class

public class calculator

public string tostring();

//perform arithmetic op represented by this constant

abstract double eval(double x,double y);

//doubly nested anonymous classes

public static final operation plus = new operation("+")

}

public static final operation minus= new operation("-")

}

public static final operation times= new operation("*")

}

public static final operation divide=new operation("/")

}

}

//return hte results of the specified calculation

public double calculate(double x,operation op,double y)

}

區域性類是四種巢狀類中最少使用的類。在任何「可以宣告區域性變數」的地方,都可以宣告區域性類。與成員類一樣,區域性類有名字,可以被重複使用。與匿名類一樣,當且僅當局部類被用於非靜態環境下的進修,它們才有外圍例項。與匿名類一樣,它必須非簡短,以不會損害外圍方法或者初始化器的可讀性。

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

《effective Java》讀後筆記

為什麼區域性變數要宣告為 final 在jdk 1.8 之前,不用final修飾會編譯報錯。在jdk 1.8 中,不用final修飾不會報錯,但是一旦改變了變數的值就會報錯 區域性類如果乙個內部類需要在多個方法之外仍然是可見的,或者是它太長了,不適合於放在方法內部,就應該使用成員類。如果成員類的每個...

Effective Java閱讀筆記

通用程式設計 將區域性變數的作用域最小化,可以增強 的可讀性和可維護性,並降低出錯的可能性。要使區域性變數的作用域最小化,最有力的方法就是在第一次使用它的地方宣告。如果變數在使用之前宣告,只會造成混亂,過早地宣告區域性變數不僅會使它的作用域擴充套件,而且結束地也過於晚了。不要重新造輪子,一般而言,類...

乙個effective java中的效率問題

package com.liuc public class autopackage long end system.currenttimemillis system.out.println end start 1000 執行時間19s 和下面這個程式 package com.liuc public ...