当前位置: 首页>后端>正文

第六十八条:遵守普遍接受的命名惯例【通用编程 end】

Java平台建立了一整套很好的命令惯例,其中有许多命令惯例包含在了《The Java Language Specification》[JLS,6.1]中。不严格的讲,这些命名惯例分为两大类:字面的和语法的。

字面的命名惯例比较少,但也涉及包、类、接口、方法、域和类型变量。应该尽量不违反这些惯例,不到万不得已,千万不要违反。如果API违反了这些惯例,使用起来可能会很困难。如果实现违反了它们,可能会难以维护。在这两种情况下,违反惯例都会潜在的给使用这些代码的其他程序员带来困惑和苦恼,并且使它们做出错误的假设,造成程序出错。本条目将对这些惯例做简要的介绍。

包和模块的名称应该是层次状的,用句号分隔每个部分。每个部分都包括小写字母,极少数情况下还有数字。任何将在你的组织之外使用的包,其名称都应该以你的组织的Internet域名开头,并且顶级域名要放在前面,例如edu.cmu、com.google、org.eff。标准类库和一些可选的包,其名称以java和javax开头。关于将Internet域名转换为包名称前缀的详细规则,请参考《The Java Language Specification》[JLS,6.1]。

包名称的其余部分应该包括一个或者多个描述改包的组成部分。这些组成部分应该比较简短,通常不超过8个字符。鼓励使用有意义的缩写形式,例如,使用util而不是utilities。只取首字母的缩写形式也是可以接受的,例如awt。每个组成部分通常都应该由一个单词或者一个缩写词组成。

许多包的名称中都只有一个组成部分再加上Internet域名。比较大的名称使用附加部分是正确的,它们的规模要求它们要被分割成一个非正式的层次结构。例如,java.util包有着非常丰富的包层次,如java.util.concurrent.atomic。这样的包通常被称为子包,尽管Java语言并没有提供对包层次的支持。

类和接口的名称,包括枚举和注解类型的名称,都应该包括一个或者多个单词,每个单词的首字母大写,例如List和FutureTask。应该尽量避免用缩写,除非是一些首字母缩写和一些通用的缩写,除非是一些首字母缩写和一些通用的缩写,比如max和min。对于首字母缩写,到底应该全部大写还是只有首字母大写,没有统一的说法。虽然有些程序员仍然采用全部大写的形式,但还是有人强列支持只首字母大写:即使连续出现多个首字母缩写的形式,你仍然可以区分出一个单词的起始处和结束处。比如类名HTTPURL和HttpUrl你更愿意看到哪一个?

方法和域的名称与类和接口的名称一样,都遵守相同的字面惯例,只不过方法或者域的第一个字母应该小写,例如remove、ensureCapacity。如果由首字母缩写组成的单词是一个方法或者域名称的第一个单词,它就应该是小写形式。

上述规则的唯一例外是“常量域”,它的名称应该包含一个或者多个大写的单词,中间用下划线符号隔开,例如VALUES或者NEGATIVE_INFINITY。常量域是一个静态final域,它的值是不可变的。如果静态final域有基本类型,或者有不可变的引用类型(详见第17条),它就是个常量域。例如,枚举常量是常量域。如果静态final域有个可变的引用类型,若被引用的对象是不可变的,它也仍然可以是个常量域。注意,常量域是唯一推荐使用下划线的情形。

局部变量名称的字面命名惯例与成员名称类似,只不过它也允许缩写,单个字符和短字符序列的意义取决于局部变量所在的上下文环境,例如i、denom和houseNum。输入参数是一种特殊的局部变量。它们的命名应该比普通的局部变量更加小心,因为它们的名称是其方法文档的一个组成部分。

类型参数名称通常由单个字母组成。这个字母通常是一下五种类型之一:T表示任意的类型,E表示集合的原始类型,K和V表示映射的键和值类型,X表示异常。函数的返回类型通常是R。任何类型的序列可以是T、U、V或者T1、T2、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条)经常用复数名词命名,如Collectors或者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 Beans规范中,它形成了早期的可重用组件架构的基础。有些现代工具继续以来Beans命名惯例,你大可放心的在那些需要结合这些工具一起使用的代码中使用。如果类中包含了用于相同属性的setter方法和getter方法,也强烈建议采用这种命名形式。在这种情况下,这两种方法应该分别被命名为getAttribute和setAttribute

有些方法的名称值得专门提及。转换对象类型的实例方法,它们返回不同类型的独立对象的方法,经常被称为toType,例如toString或者toArray。返回视图(view,详见第6条,视图的类型不同于接收对象的类型)的方法经常被称为asType,例如asList。返回一个与被调用对象同值的基本类型的方法,经常被称为typeValue,例如intValue。静态工厂常用名称包括from、of、valueOf、instance、getInstance、newInstance、getType和newType(详见第1条)。

域名称的语法惯例没有很好的建立起来,它们也没有类、接口和方法名称那么重要,因为设计良好的API很少会暴露出来的域。boolean类型的域命名与boolean类型的访问方法很类型,但是省去了初始化的is,例如initialized和composite。其他类型的域通常用名词或者名词短语来命名,例如height、digits或者bodyStyle。局部变量的语法惯例类似于域的语法惯例,但是更弱一些。

总而言之,把标准的命名惯例当作一种内在机制来看待,并且学着用它们作为第二特性。字面惯例是非常直接和明确的;语法惯例则更复杂,也更松散。下面这句话引自《The Java Language Specification》[JLS,6.1]:“如果长期养成的习惯用法与此不同,请不要盲目遵从这些命名惯例”。请使用大家公认的做法。


https://www.xamrdz.com/backend/3mc1938986.html

相关文章: