pursue wind pursue wind
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
  • EffectiveJava

    • 考虑使用静态工厂方法替代构造方法
    • 当构造方法参数过多时使用builder模式
    • 使用私有构造方法或枚类实现Singleton属性
    • 使用私有构造方法执行非实例化
    • 依赖注入优于硬连接资源(hardwiring resources)
    • 避免创建不必要的对象
    • 消除过期的对象引用
    • 避免使用Finalizer和Cleaner机制
    • 使用try-with-resources语句替代try-finally语句
    • 重写equals方法时遵守通用约定
    • 重写equals方法时同时也要重写hashcode方法
    • 始终重写 toString 方法
    • 谨慎地重写 clone 方法
    • 考虑实现Comparable接口
    • 使类和成员的可访问性最小化
    • 在公共类中使用访问方法而不是公共属性
    • 最小化可变性
    • 组合优于继承
    • 要么设计继承并提供文档说明,要么禁用继承
    • 接口优于抽象类
    • 为后代设计接口
    • 接口仅用来定义类型
    • 类层次结构优于标签类
    • 支持使用静态成员类而不是非静态类
    • 将源文件限制为单个顶级类
    • 不要使用原始类型
    • 消除非检查警告
    • 列表优于数组
    • 优先考虑泛型
    • 优先使用泛型方法
    • 使用限定通配符来增加API的灵活性
    • 合理地结合泛型和可变参数
    • 优先考虑类型安全的异构容器
    • 使用枚举类型替代整型常量
    • 使用实例属性替代序数
    • 使用EnumSet替代位属性
    • 使用EnumMap替代序数索引
    • 使用接口模拟可扩展的枚举
    • 注解优于命名模式
    • 始终使用Override注解
    • 使用标记接口定义类型
    • lambda表达式优于匿名类
    • 方法引用优于lambda表达式
    • 优先使用标准的函数式接口
    • 明智审慎地使用Stream
    • 优先考虑流中无副作用的函数
    • 优先使用Collection而不是Stream来作为方法的返回类型
    • 谨慎使用流并行
    • 检查参数有效性
    • 必要时进行防御性拷贝
    • 仔细设计方法签名
    • 明智审慎地使用重载
    • 明智审慎地使用可变参数
    • 返回空的数组或集合,不要返回 null
    • 明智审慎地返回 Optional
    • 为所有已公开的 API 元素编写文档注释
    • 最小化局部变量的作用域
    • for-each 循环优于传统 for 循环
    • 了解并使用库
    • 若需要精确答案就应避免使用 float 和 double 类型
    • 基本数据类型优于包装类
    • 当使用其他类型更合适时应避免使用字符串
    • 当心字符串连接引起的性能问题
    • 通过接口引用对象
    • 接口优于反射
    • 明智审慎地本地方法
    • 明智审慎地进行优化
    • 遵守被广泛认可的命名约定
    • 只针对异常的情况下才使用异常
    • 对可恢复的情况使用受检异常,对编程错误使用运行时异常
    • 避免不必要的使用受检异常
    • 优先使用标准的异常
    • 抛出与抽象对应的异常
    • 每个方法抛出的异常都需要创建文档
    • 在细节消息中包含失败一捕获信息
    • 保持失败原子性
    • 不要忽略异常
    • 同步访问共享的可变数据
    • 避免过度同步
    • executor 、task 和 stream 优先于线程
    • 并发工具优于 wait 和 notify
    • 文档应包含线程安全属性
    • 明智审慎的使用延迟初始化
    • 不要依赖线程调度器
    • 优先选择 Java 序列化的替代方案
    • 非常谨慎地实现 Serializable
    • 考虑使用自定义的序列化形式
    • 保护性的编写 readObject 方法
    • 对于实例控制,枚举类型优于 readResolve
    • 考虑用序列化代理代替序列化实例
  • On Java 8

  • 书
  • EffectiveJava
pursuewind
2020-11-22

遵守被广泛认可的命名约定

# 68. 遵守被广泛认可的命名约定

Java 平台有一组完善的命名约定,其中许多约定包含在《The Java Language Specification》[JLS, 6.1]。不严格地讲,命名约定分为两类:排版和语法。

有少量的与排版有关的命名约定,包括包、类、接口、方法、字段和类型变量。如果没有很好的理由,你不应该违反它们。如果 API 违反了这些约定,那么它可能很难使用。如果实现违反了这些规则,可能很难维护。在这两种情况下,违规都有可能使其他使用代码的程序员感到困惑和恼怒,并使他们做出错误的假设,从而导致错误。本条目概述了各项约定。

包名和模块名应该是分层的,组件之间用句点分隔。组件应该由小写字母组成,很少使用数字。任何在你的组织外部使用的包,名称都应该以你的组织的 Internet 域名开头,并将组件颠倒过来,例如,edu.cmu、com.google、org.eff。以 java 和 javax 开头的标准库和可选包是这个规则的例外。用户不能创建名称以 java 或 javax 开头的包或模块。将 Internet 域名转换为包名前缀的详细规则可以在《The Java Language Specification》[JLS, 6.1] 中找到。

包名的其余部分应该由描述包的一个或多个组件组成。组件应该很短,通常为 8 个或更少的字符。鼓励使用有意义的缩写,例如 util 而不是 utilities。缩写词是可以接受的,例如 awt。组件通常应该由一个单词或缩写组成。

除了 Internet 域名之外,许多包的名称只有一个组件。附加组件适用于大型工具包,这些工具包的大小要求将其分解为非正式的层次结构。例如 javax.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 表示 Map 的键和值类型,X 表示异常。函数的返回类型通常为 R。任意类型的序列可以是 T、U、V 或 T1、T2、T3。

为了快速参考,下表显示了排版约定的示例。

Identifier Type Example
Package or module org.junit.jupiter.api, com.google.common.collect
Class or Interface Stream, FutureTask, LinkedHashMap,HttpClient
Method or Field remove, groupingBy, getCrc
Constant Field MIN_VALUE, NEGATIVE_INFINITY
Local Variable i, denom, houseNum
Type Parameter T, E, K, V, X, R, U, V, T1, T2

语法命名约定比排版约定更灵活,也更有争议。包没有语法命名约定。可实例化的类,包括枚举类型,通常使用一个或多个名词短语来命名,例如 Thread、PriorityQueue 或 ChessPiece。不可实例化的实用程序类(详见第 4 条)通常使用复数名词来命名,例如 collector 或 Collections。接口的名称类似于类,例如集合或比较器,或者以 able 或 ible 结尾的形容词,例如 Runnable、Iterable 或 Accessible。因为注解类型有很多的用途,所以没有哪部分占主导地位。名词、动词、介词和形容词都很常见,例如,BindingAnnotation、Inject、ImplementedBy 或 Singleton。

执行某些操作的方法通常用动词或动词短语(包括对象)命名,例如,append 或 drawImage。返回布尔值的方法的名称通常以单词 is 或 has(通常很少用)开头,后面跟一个名词、一个名词短语,或者任何用作形容词的单词或短语,例如 isDigit、isProbablePrime、isEmpty、isEnabled 或 hasSiblings。

返回被调用对象的非布尔函数或属性的方法通常使用以 get 开头的名词、名词短语或动词短语来命名,例如 size、hashCode 或 getTime。有一种说法是,只有第三种形式(以 get 开头)才是可接受的,但这种说法几乎没有根据。前两种形式的代码通常可读性更强,例如:

if (car.speed() > 2 * SPEED_LIMIT)
    generateAudibleAlert("Watch out for cops!");
1
2

以 get 开头的表单起源于基本过时的 Java bean 规范,该规范构成了早期可重用组件体系结构的基础。有一些现代工具仍然依赖于 bean 命名约定,你应该可以在任何与这些工具一起使用的代码中随意使用它。如果类同时包含相同属性的 setter 和 getter,则遵循这种命名约定也有很好的先例。在本例中,这两个方法通常被命名为 getAttribute 和 setAttribute。

一些方法名称值得特别注意。转换对象类型(返回不同类型的独立对象)的实例方法通常称为 toType,例如 toString 或 toArray。返回与接收对象类型不同的视图(详见第 6 条)的方法通常称为 asType,例如 asList。返回与调用它们的对象具有相同值的基本类型的方法通常称为类型值,例如 intValue。静态工厂的常见名称包括 from、of、valueOf、instance、getInstance、newInstance、getType 和 newType(详见第 1 条,第 9 页)。

字段名的语法约定没有类、接口和方法名的语法约定建立得好,也不那么重要,因为设计良好的 API 包含很少的公开字段。类型为 boolean 的字段的名称通常类似于 boolean 访问器方法,省略了初始值「is」,例如 initialized、composite。其他类型的字段通常用名词或名词短语来命名,如 height、digits 和 bodyStyle。局部变量的语法约定类似于字段的语法约定,但要求更少。

总之,将标准命名约定内在化,并将其作为第二性征来使用。排版习惯是直接的,而且在很大程度上是明确的;语法惯例更加复杂和松散。引用《The Java Language Specification》[JLS, 6.1] 中的话说,「如果长期以来的传统用法要求不遵循这些约定,就不应该盲目地遵循这些约定。」,应使用常识判断。

Last Updated: 2023/01/30, 11:01:00
明智审慎地进行优化
只针对异常的情况下才使用异常

← 明智审慎地进行优化 只针对异常的情况下才使用异常→

Theme by Vdoing | Copyright © 2019-2023 pursue-wind | 粤ICP备2022093130号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜
  • 网络DJ