1.[强制] 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
反例: _name / __name / $name / name_ / name$ / name__
老四附言:
Java本身就要求自己的命名规则。
Java源文件的命名规则:
- Java程序源文件的后缀必须是.java,不能是其他文件后缀名。
- 在通常情况下,Java程序源文件的主文件名可以使任意的。但有一种情况例外: 如果Java程序源代码里定义了一个public类,则该源文件的主文件名必须与该public类(也就是该类定义使用了public关键字修饰)的类名相同。
- 由于Java程序源文件的文件名必须与public类的类名相同,因此,一个Java源文件里最多只能定义一个public类。
标识符规则:
- 标识符就是用于给程序中变量、类、方法命名的符号。Java语言的标识符必须以字母、下划线(_)、美元符号($)开头,后面可以跟任意数目的字母、数字、下划线和美元符号。此处的字母并不局限于26个英文字母,而且可以包含中文字符、日文字符等。
- 标识符可以由字母、数字、下划线和美元符号组成,其中数字能打头。
- 标识符不能是Java关键字和保留字,但可以包含关键字和保留字。
- 标识符不能包含空格。
- 标识符只能包含美元符号,不能包含@、#等其他特殊字符。
2.[强制] 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
说明: 正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。
正例: alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。
反例: DaZhePromotion [ 打折 ] / getPingfenByName() [ 评分 ] / int 某变量 = 3
老四附言:
纯拼音的方式命名太Low了,也不利于理解,即使英文再不好用个谷歌翻译也比拼音强。
3.[强制] 类名使用UpperCamelCase(大驼峰)风格,但以下情形例外: DO / BO / DTO / VO / AO / PO等。
正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例: macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
老四附言:
关于DO / BO / DTO / VO / AO / PO的解释以及他们的使用场景,老四在之前的《阿里巴巴Java开发手册第六章-应用分层篇》文章中做过一些基本的说明,可以前去参考一下。
4.[强制] 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase(小驼峰)风格,必须遵从驼峰形式。
正例: localValue / getHttpMessage() / inputUserId
老四附言:
与第三条规约相对应,类名使用大驼峰,首字母要大写,成员、方法、变量等要使用小驼峰,首字母小写。
5.[强制] 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例: MAX_STOCK_COUNT
反例: MAX_COUNT
老四附言:
老主观认为常量命名全部大写是带有强烈标识作用性的,一眼就能看出来这是声明的常量,而采用驼峰或者小写的时候往往更容易第一眼觉得这是个局部变量,造成混淆。
6.[强制] 抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类名开始,以Test结尾。
老四附言:
抽象类作为基类或者说超类,应该给予其明显的被继承标识,这样开发人员无须进入该类就能判断他是抽象类。同理,异常和测试类在命名的时候赋予其明显的命名标识,给代码阅读和开发过程带来极大的方便,一眼就知道这个是用来干嘛的,不比按住ctrl进去看看里面的具体内容,节省时间精力。
7.[强制] 类型与中括号紧挨相连来定义数组。
正例: 定义整形数组 int[] arrayDemo;
反例: 在main参数中,使用String args[]来定义。
老四附言:
表达数组的过程中,数组符号”[]”是属于类型的一部分,所以类型与中括号紧挨书写是比较正确的做法,虽然将”[]”放在实例名称的后面也不算错,但是稍显别扭,表达该变量是数组的程度也不是十分明显。
8.[强制] POJO(Plain Ordinary Java Object,简单的Java对象)类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误。
反例: 定义为基本数据类型Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC(Remote Procedure Call,远程过程调用)框架在反向解析的时候,”误以为”对应的属性名称是deleted,导致属性获取不到,进而抛出异常。
老四附言:
这就是前辈的经验了,大家注意遵守就好。
9.[强制] 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
正例: 应用工具类包名为com.alibaba.ai.util、类名为MessageUtils(此规则参考spring的框架结构)
老四附言:
包名使用单数形式是为了抽象表达的包里面包含的业务属性,而不是表达具体的业务形式,所以使用单数形式,而里面的类涉及到一般都是具体的业务类或者说跟项目息息相关的Java程序,所以需要表达多的意思时候要使用复数。但是老四个人觉得,util包下面的各个util工具类其实真心没必要使用utils,因为util就是代表工具,一个类其实应该代表的就是一个工具,不需要加复数。可能老外的思想是觉得一个工具类里面包含了很多操作该业务的方法,所以使用的复数吧。
10.[强制] 杜绝完全不规范的缩写,避免望文不知义。
反例: AbstractClass”缩写”命名成AbsClass;condition”缩写”命名成condi,此类随意缩写严重降低了代码的可阅读性。
老四附言:
(⊙o⊙)…其实老四有的时候也总犯这个错误,回过头来自己看的时候都骂自己当年写的代码都是些屎….
11.[推荐] 为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。
正例: 从远程仓库拉取代码的类命名为PullCodeFromRemoteRepository。
反例: 变量int a;的随意命名方式。
老四附言:
是这样的,完整的词组一看便知道业务代码是拿来干嘛的,免去翻注释找同事询问的烦恼。
12.[推荐] 如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。
说明: 将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:
1 2 3 |
public class OrderFactory; public class LoginProxy; public class ResourceObserver; |
老四附言:
关于设计模式,老四目前也在逐渐的浅析GoF的设计模式,闲着没事的时候大家也可以一起交流一下。
13.[推荐] 接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性,并加上有效的Javadoc注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。
正例:
- 接口方法签名: void f();
- 接口基础常量: String COMPANY = “alibaba”;
反例:
- 接口方法定义: public abstract void f();
说明: JDK8中接口允许有默认实现,那么这个default方法,是对所有实现类都有价值的默认实现。
老四附言:
Java8中关于接口新增的一些特性:
我们都知道接口体现的规范和实现分离的设计哲学,在软件系统中,各组件之间面向接口耦合,各模块之间也采用面向接口耦合,尽最大程度降低模块之间的耦合度,为系统提供的更好的可扩展性和可维护性。之前Java中的接口里不能包含普通方法,接口里面的所有方法都是抽象方法。Java8对接口进行了改进,允许接口中定义默认方法,默认方法可以提供方法的实现。
- Java8允许在接口中定义默认方法,默认方法必须使用default修饰,该方法不能使用static修饰,无论是否是自己手动指定,默认方法总是使用public修饰,没有的话程序自动默认给方法添加public修饰符。
- Java8允许使用在接口中定义类方法,类方法必须使用static修饰而且不能使用default修饰了。同上,方法依然使用public来修饰,没有手动指定的话系统程序自动为方法添加publc修饰符。
基本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package com.glorze.interface; /** * Java8中改进的接口 * @ClassName Glorze * @author: 高老四 * @since: 2018年10月25日 上午11:33:55 */ public interface Glorze { /** * 接口定义的成员变量只能是常量 * 系统自动增加 public static */ Integer MAX_CACHE_COUNT = 50; /** * 接口中定义的普通方法只能是public的抽象方法 * 系统自动增加 public abstract * @Title: glorze * @return void * @author: glorze.com * @since: 2018年10月25日 上午11:35:07 */ void glorze(); /** * 抽象方法getNumber前面系统自动添加public abstract * @Title: getNumber * @return void * @author: 高老四 * @since: 2018年10月25日 上午11:35:55 */ void getNumber(); /** * 在街口中定义默认方法,需要使用default修饰 * @Title: print * @return void * @author: glorze.com * @since: 2018年10月25日 上午11:37:47 */ default void print() { System.out.println("Java8改进的接口新特性浅析-高老四博客-glorze.com-倚楼听风雨淡看江湖路"); } /** * 在接口中定义类方法,需要使用static修饰,类方法可以直接使用接口来调用。 * @Title: wirte * @return String * @author: 高老四 * @since: 2018年10月25日 上午11:39:22 */ static String wirte() { return "测试接口中的类方法"; } } |
另外,我们经常在面试题或者笔试题中遇到关于Java中接口和抽象类的比较,老四之前在文章《浅析设计模式第十章-模板方法模式》中做过基本的讲解,大家可以去参考一下。
注意:还有一个知识点就是我们都知道Java中类是单继承多接口的,但是接口中的继承和类继承是不一样的,接口完全支持多继承,一个接口可以有多个直接父接口。
14.接口和实现类的命名有两套规则:
- [强制] 对于Service和DAO类,基于SOA(Service-Oriented Architecture,面向服务的体系结构)的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。
- [推荐] 如果是形容能力的接口名称,取对应的形容词为接口名(通常是–able的形式)。
正例:
- CacheServiceImpl实现CacheService接口。
- AbstractTranslator实现Translatable。
老四附言:
还是那句话,好的规约使得我们会有良好的编码习惯的同时,会使代码阅读体验大幅提升,代码阅读起来意思清晰明了。
15.[参考] 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。
说明: 枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
正例: 枚举名字为ProcessStatusEnum的成员名称: SUCCESS / UNKNOWN_REASON。
老四附言:
关于枚举的基础知识和使用注意事项老四之前在文章《阿里巴巴Java开发规约第一章-注释规约篇》中第五条规约做过一些浅析和复习,诸君可以前去参考一下。
16.[参考] 各层命名规约:
Service/DAO层方法命名规约:
- 获取单个对象的方法用get作前缀。
- 获取多个对象的方法用list作前缀。
- 获取统计值的方法用count作前缀。
- 插入的方法用save/insert作前缀。
- 删除的方法用remove/delete作前缀。
- 修改的方法用update作前缀。
领域模型命名规约:
- 数据对象: xxxDO,xxx即为数据表名。
- 数据传输对象: xxxDTO,xxx为业务领域相关的名称。
- 展示对象: xxxVO,xxx一般为网页名称。
- POJO是DO/DTO/BO/VO的统称,禁止命名成 xxxPOJO。
老四附言:
这也算是经过前辈们的使用经验和多年的代码积累而成的一条规约,对应的规则清晰明了的表达了对应的业务表述,现在逐渐成了明文规定,也不失为好事一件。
更博不易,如果觉得文章对你有帮助并且有能力的老铁烦请赞助盒烟钱,点我去赞助。或者扫描文章下面的微信/支付宝二维码打赏任意金额,老四这里抱拳了。赞助时请备注姓名或者昵称,因为您的署名会出现在赞赏列表页面,您的赞赏钱财也会被用于小站的服务器运维上面,再次抱拳。