编程规约(上) -- 阿里巴巴Java开发手册
没有标注 "推荐" 等字样的, 为强制标准.
加粗的为不熟悉的.
一.命名风格
1-1.代码中的命名均不能以下划线或美元符号开始或结束
String _name, $name; // not
1-2.严禁使用拼音和英文混合,不能使用中文, 国际通用的名称,可视同英文
String getPingfenByName; //not
1-3.类名使用驼峰命名,首字母大写,DO / BO / DTO / VO / AO / PO /UID 等除外
1-4.方法名,参数名,变量都采用 lowerCanelCase 风格
1-5.常量命名全部大写,单词间用下划线隔开.不要嫌名字长,语意表达完整
String MAX_STOCK_COUNT;
1-6.抽象类名使用 Abstract 或 Base 开头,异常类名使用 Exception 结尾,测试类名以它要测试的类名开始 ,Test 结尾。
1-7.表示数组, 类型[] 变量名;
int[] arrayDemo; //yes
int arrayDemo1[]; //not
1-8.POJO类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误.
Boolean isDelete; //not
1-9.包名统一使用小写,点分隔符之间有且仅有一个自然语义的单词;包名统一使用单数形式,类名可以使用复数形式。
1-10.杜绝不规范的缩写导致望文不知义 Condition --> condi
推荐:
1-11.任何自定义编程元素在命名时尽量使用完整的单词组合来表达, 反例 int a;
1-12.如果模块,接口,类,方法使用了设计模式,在命名时需体现出具体模式。
例如:OrderFactory,LoginProxy, ResourceObserver
1-13.接口类中的方法和属性不要加任何的修饰符号(public也不加),并加上有效的JavaDoc注释。
尽量不要在接口里定义变量,如果要,肯定是与接口方法相关,,并且是整个应用的基础常量。
JDK8 default方法,是对所有实现类都有价值的默认实现
1-14.接口和实现类的命名有两套规则
1) 对于 Service 和 DAO类, 基于 SOA的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 后缀区分
2) (推荐) 如果是形容能力的接口名称,取对应的形容词为接口名( -able 形式)
参考:
1-15.枚举类建议带上Enum后缀, 枚举成员名称需要全大写,单词间用下划线隔开。
枚举类就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。
例如:枚举名为 ProcessStatusEnum , 成员名 SUCCESS / UNKNOWN_REASON
1-16.各层命名规约:
A)Service/DAO 层方法命名规约
1) 获取单个对象的方法用 get 做前缀。
2) 获取多个对象的方法用 list 做前缀,复数形式结尾如:listObjects。
3) 获取统计值的方法用 count 做前缀。
4) 插入的方法用 save/insert 做前缀。
5) 删除的方法用 remove/delete 做前缀。
6) 修改的方法用 update 做前缀。
B)领域模型命名规约
1) 数据对象:xxxDO,xxx 即为数据表名。
2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
3) 展示对象:xxxVO,xxx 一般为网页名称。
4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
二.常量定义
2-1.不允许使用任何魔法值(即未经预先定义的常量) 直接出现在代码中.
例如: int priceTable[] = new int[16]; //ERROR:这个16究竟有何含义呢?
2-2.在使用Long或者long赋值时, 数值后使用大写的L
推荐:
2-3.不要使用一个常量类维护所有常量,要按照常量功能进行归类.
2-4.常量的复用层次有五层: 跨应用共享,应用内共享,子工程内共享,包内共享,类内共享
1) 跨应用: 放置在二方库中,通常是 client.jar 中的 constant 目录下
2) 应用内: 放置在一方库中,通常是子模块中的 constant 目录下
3) 子工程内: 即在当前子工程的 constant 目录下
4) 包内: 即在当前包下单独的constant目录下
5) 类内: 直接在类内部 private static final 定义.
2-5.如果变量值仅在一个固定范围内变化,用enum类型来定义
三.代码格式
3-1.大括号的使用约定,大括号内为空,写成 { } 即可. 非空写成以下格式
public void method() { //1.左大括号前不换行,后换行. 2.左大括号前需要空格
}//右大括号前换行,后还有else则不换行,表示中止的右大括号必须换行
3-2.小括号和字符之间不出现空格
if ( a==b ) //not
3-3.if /for /while /switch /do 等保留字与括号之间都必须加空格
3-4.任何二目,三目运算符的左右两边都需要一个空格.
3-5.采用4个空格缩进,禁止使用tab字符
说明:如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。IDEA 设置 tab 为 4 个空格时,
请勿勾选 Use tab character;而在 eclipse 中,必须勾选 insert spaces for tabs。
//正例 (1-5)
public static void main(String[] args) {
// 缩进 4 个空格
String say = "hello";
// 运算符的左右必须有一个空格
int flag = 0;
// 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格
if (flag == 0) {
System.out.println(say);
}
// 左大括号前加空格且不换行;左大括号后换行
if (flag == 1) {
System.out.println("world");
// 右大括号前换行,右大括号后有 else,不用换行
} else {
System.out.println("ok");
// 在右大括号后直接结束,则必须换行
}
}
3-6.注释的双斜线与注释内容之间有且仅有一个空格
3-7.单行字符数限制不超过120个, 超出换行, 换行原则 :
1) 第二行相对第一行缩进4空格,第三行开始不再缩进
2) 运算符与下文一起换行
3) 方法调用点符号与下文一起换行
4) 方法调用中的参数需要换行时,在逗号后进行
5) 在括号前不要换行,逗号前不要换行
3-8.方法参数在定义和传入时,多个参数逗号后必须加空格
3-9.IDE的 test file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix格式, 不要使用windows格式.
推荐 :
3-10.单个方法的总行数不超过80行,包括注释,大括号,空行等.
代码逻辑分清红花和绿叶,个性和共性,
绿叶逻辑单独出来成为额外方法,使主干代码更加清晰.
共性逻辑抽取成共性方法,便于维护和复用.
3-12.不同逻辑,不同语义,不同业务的代码之间插入一个空行分隔开来以提升可读性. 不必插入多个空行.
四.OOP规约
4-1.不要使用一个类的对象引用访问此类的静态变量或静态方法, 无畏增加编译器解析成本.
4-2.所有的覆写方法,必须加@Override 注解
4-3.相同参数类型,业务含义,才可以使用可变参数,避免使用Object. (提倡尽量不使用可变参数编程)
4-4.外部正在调用或者二方库依赖的接口, 不允许修改方法签名.
接口过时必须加 @Deprecated 注解,并清晰的说明采用的新接口或者新服务是什么
4-5.不能使用过时的类或方法.
4-6.equals方法,应使用常量或确定有值的对象来调用. 推荐使用 java.util.Objects#equals (JDK7引入的工具类)
4-7.所有的相同类型的包装类对象之间值的比较,全部用equals方法比较. 包装类:Integer等
4-8.关于基本数据类型与包装数据类型的使用标准如下:
1) 所有的POJO类属性必须使用包装数据类型
2) RPC方法的返回值和参数必须使用包装数据类型
3) (推荐) 所有的局部变量使用基本数据类型
4-9.定义DO/DTO/VO 等POJO类时, 不要设定任何属性默认值
4-10.序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败.
4-11.构造方法里面禁止加入任何业务逻辑, 如果有初始化逻辑,请放在 init 方法中.
4-12.POJO类必须写 toString 方法.如果继承了另一个POJO ,注意在前面加一下 super.toString
4-13.禁止在POJO类中,同时存在对应属性的 isXxx() 和 getXxx() 方法.
说明:框架在调用属性Xxx的提取方法时,不确定哪个方法被优先调用到
推荐:
4-14.使用索引访问用String split 方法得到的数组时,需做最后一个分隔符后有无内容的检查.
String str = "a,b,c,,";
String[] ary = str.split(",");
System.out.println(ary.length); //3
4-15.当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读.优先于16条规则.
4-16.类内方法定义的顺序依次是: 公有方法或保护方法 >私有方法 >getter/setter 方法.
4-17.setter方法中,参数名称与类成员变量名称一致,不要在方法中增加业务逻辑,增加排查问题的难度.
4-18.循环体内,字符串的连接方式,使用StringBuilder 的 append 方法进行扩展.
4-19.final 可以声明类,成员变量,方法,以及本地变量.
1) 不允许被继承的类
2) 不允许修改引用的域对象
3) 不允许被重写的方法,例如 setter 方法
4) 不允许运行过程中重新赋值的局部变量
5) 避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好的进行重构. ??
4-20.慎用Object的clone方法来拷贝对象(浅拷贝),若要实现深拷贝需要重写clone方法实现域对象的深度遍历式拷贝
4-21.类成员与方法访问控制从严 :
1) 如果不允许直接通过new来创建对象, 构造方法必须私有
2) 工具类不允许有public 或 default构造方法
3) 类中非static成员变量并且与子类共享,必须是protected
4) 类中非static成员变量并且仅在本类使用,必须是private
5) 类中static成员变如果仅在本类使用,必须是private
6) 若是static成员变量,考虑是否为final
7) 类成员方法只供内部调用,必须是private
8) 类成员方法只对继承类公开,那么限制为protected
说明: 任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。
思考:如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 成员方法或 成员变量,删除一下,不得手心冒点汗吗?