Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼裏方法是基於Java 9 API中的,因此JDK 最好下載 JDK 9以上的版本。java
Java平臺有一組完善的命名約定(naming conventions),其中許多約定包含在Java語言規範[JLS, 6.1]中。寬泛地說,命名約定分爲兩類:字面(typographical)的和語法的(grammatical)。git
只有少許的字面的命名約定,包括包、類、接口、方法、屬性和類型變量。你不該該違反它們,並且沒有理由去違反。若是API違反了這些約定,那麼它可能很難使用。若是實現違反了這些規則,可能很難維護。在這兩種狀況下,違反約定都有可能使其餘使用代碼的程序員感到困惑和惱怒,並可能致使他們作出錯誤的假設,從而致使錯誤。本條目概述了各個命名約定。程序員
包和模塊名稱應該是分層的,每一個部分以句點分隔。 每一個部分應包含小寫字母字符,不多包含數字。任何在你的組織外部使用的包的名稱都應該以你的組織的Internet域名開頭,但包名正好相反,例如,edu.cmu,com.google,org.eff。 名稱以java和javax開頭的標準類庫和可選包是此規則的例外。 用戶不得建立名稱以java或javax開頭的包或模塊。 能夠在JLS [JLS, 6.1]中找到將Internet域名轉換爲包名稱前綴的詳細規則。github
包名的其他部分應該由描述包的一個或多個組件構成。組件應該很短,一般爲8個或更少的字符。鼓勵使用有意義的縮寫,例如util而不是utilities。縮寫詞是能夠接受的,例如awt。組件一般應該由一個單詞或縮寫組成。api
除了Internet域名以外,許多包的名稱只包含一個組件。 其餘組件適用於大型設施,其大小要求將其分解爲非正式層次結構。 例如,javax.util包具備豐富的包層次結構,其名稱如java.util.concurrent.atomic。 這樣的包被稱爲子包,儘管幾乎沒有語言對包層次結構提供支持。app
類和接口名稱(包括枚舉和註解類型名稱)應由一個或多個單詞組成,每一個單詞的首字母大寫,例如List或FutureTask。 除了首字母縮略詞和某些經常使用縮寫(如max和min)以外,應避免使用縮寫。 關於首字母縮略詞是大寫仍是僅首字母大寫,存在一些分歧。 雖然一些程序員仍然使用大寫字母,可是能夠作出強有力的論證,只支持大寫第一個字母:即便多個首字母縮寫連續出現,仍然能夠知道一個單詞從哪裏開始,下一個單詞從哪裏結束。 你更喜歡看哪一個類名,HTTPURL或HttpUrl?工具
方法和屬性名遵循與類和接口名相同的字面約定,除了方法或屬性名的第一個字母應該是小寫,例如remove或ensureCapacity。 若是首字母縮略詞做爲方法或屬性名稱的第一個單詞出現,則它應該是小寫的。google
前面規則的惟一例外是「常量屬性」,它的名稱應該由一個或多個大寫單詞組成,由下劃線分隔,例如VALUES或NEGATIVE_INFINITY。常量屬性是一個靜態的final屬性,其值是不可變的。若是靜態final屬性具備基本類型或不可變引用類型(條目 17),那麼它就是常量屬性。例如,枚舉常量是常量屬性。若是靜態final屬性有一個可變的引用類型,那麼若是所引用的對象是不可變的,那麼它仍然能夠是一個常量屬性。注意,常量屬性是惟一推薦的下劃線用法。atom
局部變量名稱與成員名稱具備類似的字面命名約定,但容許使用縮寫除外,單個字符和短字符序列的含義取決於它們出現的上下文,例如i,denom,houseNum。 輸入參數是一種特殊的局部變量。 它們的名稱應該比普通的局部變量更加仔細,由於它們的名稱是其方法文檔中不可或缺的一部分。設計
類型參數名一般由單個字母組成。最多見的是如下五種類型之一:T表示任意類型,E表示集合的元素類型,K和V表示映射的鍵和值類型,X表示異常。方法的返回類型一般爲R。任意類型的序列能夠是T、U、V或T一、T二、T3。
爲了快速參考,下表列出了字面約定的示例。
標識符類型 | 示例 |
---|---|
包名或模塊 | org.junit.jupiter.api, com.google.common.collect |
類或接口 | Stream, FutureTask, LinkedHashMap, HttpClient |
方法或屬性 | remove, groupingBy, getCrc |
常量屬性 | MIN_VALUE, NEGATIVE_INFINITY |
局部變量 | i, denom, houseNum |
類型參數 | T, E, K, V, X, R, U, V, T1, T2 |
語法命名約定比字面約定更靈活,也更有爭議。包沒有語法命名約定。可實例化的類,包括枚舉類型,一般使用一個或多個名詞短語來命名,例如Thread、PriorityQueue或ChessPiece。不可實例化的實用程序類(條目 4)一般使用複數名詞來命名,例如Collector或Collections。接口的名稱相似於類,例如Collection或Comparator,或者以able或ible結尾的形容詞,例如Runnable、Iterable或Accessible。由於註解類型有如此多的用途,因此沒有哪部分詞性占主導地位。名詞、動詞、介詞和形容詞都很常見,例如,BindingAnnotation、Inject、ImplementedBy或Singleton。
執行某些操做的方法一般使用動詞或動詞短語(包括對象)命名,例如append或drawImage。 返回boolean類型的方法一般具備以單詞is,或不太經常使用的has開頭的名稱,後跟名詞,名詞短語或任何用做形容詞的單詞或短語,例如isDigit,isProbablePrime,isEmpty, isEnabled,或hasSiblings。
方法返回被調用對象的非boolean的方法或屬性,一般使用以get開頭的名詞、名詞短語或動詞短語來命名,例如size、hashCode或getTime。有一種說法是,只有第三種形式(以get開頭)纔是可接受的,但這種說法幾乎沒有根據。前兩種形式的代碼一般可讀性更強,例如:
if (car.speed() > 2 * SPEED_LIMIT) generateAudibleAlert("Watch out for cops!");
以get開頭的形式起源於基本過期的Java bean規範,該規範構成了早期可重用組件體系結構的基礎。有一些現代工具繼續依賴於Beans命名約定,你能夠隨意在任何與這些工具結合使用的代碼中使用它。若是類同時包含相同屬性的setter和getter,則遵循這種命名約定也有很好的先例。在本例中,這兩個方法一般被命名爲getAttribute和setAttribute。
一些方法名稱值得特別說起。 轉換對象類型,返回不一樣類型的獨立對象的實例方法一般稱爲toType,例如toString或toArray。 返回類型與接收對象類型不一樣的視圖(條目 6)的方法一般稱爲asType,例如asList。 返回與調用它們的對象具備相同值的基本類型的方法一般稱爲typeValue,例如intValue。 靜態工廠的經常使用名稱包括from,of,valueOf,instance,getInstance,newInstance,getType和newType(條目 1,第9頁)。
屬性名稱的語法約定不太完善,而且不如類,接口和方法名稱那麼重要,由於設計良好的API包含不多的暴露屬性。 boolean類型的屬性一般被命名爲boolean 訪問器方法,省略了初始的is前綴,例如,initialized,composite。 其餘類型的屬性一般以名詞或名詞短語命名,例如height,digits或bodyStyle。 局部變量的語法約定相似於屬性,但甚至更弱。
總之,將標準命名約定內在化,並將其做爲次日性來使用。字面約定是直接的,並且在很大程度上是明確的;語法約定更加複雜和鬆散。引用Java語言規範[JLS, 6.1]中的話說,「若是長期以來的傳統用法要求不遵循這些約定,就不該該盲目地遵循這些約定」。使用常識。