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]中的话说,“若是长期以来的传统用法要求不遵循这些约定,就不该该盲目地遵循这些约定”。使用常识。