Java开发手册笔记(一) 编程规约

阿里巴巴Java开发规范精要
本文提炼了阿里巴巴Java开发手册中的关键规范,涵盖命名风格、代码格式、OOP规约、集合处理、并发处理及控制语句等内容,旨在提升代码质量和开发效率。

此文为阅读阿里巴巴Java开发手册时,将个人认为重要或值得注意的规范记作学习笔记。此为第一章——编程规约。

命名风格

各层命名规约(No.16)

  • Service/DAO 层方法命名规约
    1. 获取单个对象的方法用 get 做前缀。
    2. 获取多个对象的方法用 list 做前缀,复数形式结尾如:listObjects。
    3. 获取统计值的方法用 count 做前缀。
    4. 插入的方法用 save/insert 做前缀。
    5. 删除的方法用 remove/delete 做前缀。
    6. 修改的方法用 update 做前缀。
  • 领域模型命名规约
    1. 数据对象:xxxDO,xxx 即为数据表名。
    2. 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
    3. 展示对象:xxxVO,xxx 一般为网页名称。
    4. POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

常量定义

固定范围变量值使用Enum(No.5)

如果变量值仅在一个固定范围内变化用 enum 类型来定义。

说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。

public enum SeasonEnum {
	SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);
 	private int seq;

 	SeasonEnum(int seq){
 		this.seq = seq;
 	}
}

代码格式

IDE代码格式(No.9)

IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,
不要使用 Windows 格式。

OOP规约

包装类值比较(No.7)

所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。

说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

基本数据类型与包装数据类型的使用标准(No.8)

  1. 【强制】所有的 POJO 类属性必须使用包装数据类型。
  2. 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
  3. 【推荐】所有的局部变量使用基本数据类型。

说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE 问题,或者入库检查,都由使用者来保证。
正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用
不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装
数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

String#spilt()(No.14)

使用索引访问用 String 的 split 方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛 IndexOutOfBoundsException 的风险。

说明:

String str = "a,b,c,,"; 
String[] ary = str.split(","); 
// 预期大于 3,结果是 3
System.out.println(ary.length); 

集合处理

Arrays.asList()(No.5)

使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方
法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

说明: asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。 Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。

 String[] str = new String[] { "you", "wu" };
 List list = Arrays.asList(str);

第一种情况:list.add("yangguanbao"); 运行时异常。
第二种情况:str[0] = "gujin"; 那么 list.get(0)也会随之修改。

集合初始化(No.10)

集合初始化时,指定集合初始值大小。

说明:HashMap 使用 HashMap(int initialCapacity) 初始化。
正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。
反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容量 7 次被迫扩大,resize 需要重建 hash 表,严重影响性能。

entrySet 遍历 Map 类集合 KV(No.11)

使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

说明: keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出key 所对应的 value。 而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用 Map.foreach 方法。

正例:values()返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是
一个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。

并发处理

多线程共享变量安全性(No.13)

volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,
但是如果多写,同样无法解决线程安全问题。
如果是 count++操作,使用如下类实现:

AtomicInteger count = new AtomicInteger();
count.addAndGet(1); 

如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。

控制语句

高并发场景避免使用“等于”判断(No.3)

在高并发场景中,避免使用“等于”判断作为中断或退出的条件。

说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间
判断条件来代替。

反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变
成了负数,这样的话,活动无法终止。

参数校检(No.9)

  1. 调用频次低的方法。
  2. 执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失。
  3. 需要极高稳定性和可用性的方法。
  4. 对外提供的开放接口,不管是 RPC/API/HTTP 接口。
  5. 敏感权限入口。

其他

后台传输变量(No.3)

后台输送给页面的变量必须加$!{var}——中间的感叹号。

说明:如果 var 等于 null 或者不存在,那么${var}会直接显示在页面上。


资料来源:
1.阿里巴巴Java开发手册(1.4.0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值