java编码规范
所属分类 java
浏览量 1568
参考 Alibaba Java Coding Guidelines
https://github.com/alibaba/p3c
BLOCKER,CRITICAL,MAJOR
并发,集合,命名风格,常量定义, OOP规约,控制语句,异常处理,代码风格,注释等
并发处理
1 [CRITICAL] 必须清理自定义的ThreadLocal变量,在 finally 块处理
2 [CRITICAL] 创建线程或线程池时指定有意义的名称,方便排查定位问题。
public class MyTaskThread extends Thread {
public MyTaskThread(){
super.setName("MyTaskThread");
}
}
3 [BLOCKER] 使用线程池,不建议在应用中显式创建线程
减少在创建和销毁线程上所消耗的时间以及系统资源开销
大量创建类线程 消耗完内存 过度切换
4 [BLOCKER] 线程池不要使用Executors去创建,而是通过ThreadPoolExecutor方式,明确线程池的运行规则,规避资源耗尽的风险。
Executors 返回的线程池对象的问题
1) FixedThreadPool 和 SingleThreadPool
最大请求队列长度为 Integer.MAX_VALUE.可能会堆积导致OOM
2) CachedThreadPool:
允许创建线程数为 Integer.MAX_VALUE. 可能会创建大量的线程,导致OOM
5 [CRITICAL] SimpleDataFormat非线程安全
使用DateUtils,推荐以下用法
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
6 [BLOCKER] Timer 和 ScheduledExecutorService 任务注意处理 异常
Timer和ScheduledExecutorService的区别
7 [MAJOR] 使用 CountDownLatch 每个线程退出时确保 调用 countDown 方法
8 [MAJOR] 避免 Random 实例被多线程使用,虽然该实例是线程安全的,但会因竞争同一 seed 导致性能下降。
JDK7 之后 可以直接使用 ThreadLocalRandom
集合处理
1 [CRITICAL] ArrayList 的 subList 结果不可强转成 ArrayList,会抛 ClassCastException 异 常,java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
subList 返回 ArrayList 的内部类 SubList, 是 ArrayList 的一个视图,对于 SubList 所有操作最终会反映到原列表上。
2 [CRITICAL] 在subList场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍 历、增加、删除产生 ConcurrentModificationException 异常。
3 [CRITICAL] 集合转数组使用集合的toArray(T[]array),传入类型一致且长度为 0 的空数组。
List list = new ArrayList(2);
list.add("a");
list.add("b");
String[] array = new String[0];
array = list.toArray(array);
the array into which the elements of this list are to be stored,
if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
传入的数组容量够大,直接返回,否则新创建一个数组
4 [CRITICAL] Arrays.asList() 数组转换成集合,不能使用 add/remove/clear 等方法 ,否则 UnsupportedOperationException
Arrays.asList 返回 Arrays 内部类,并没有实现集合的修改方法。
java.util.Arrays$ArrayList
包装了数组 , 是数组的视图
5 [BLOCKER] 不要在 foreach 循环 调用 remove/add 操作
list 遍历删除元素的正确做法
Iterator it = list.iterator();
while(it.hasNext()){
Integer item = it.next();
if (item.intValue() % 2 == 0) {
it.remove();
}
}
集合遍历删除注意点
6[MAJOR] 集合初始化时,指定集合初始值大小 说明:HashMap 使用 HashMap(int initialCapacity) 初始化
命名风格
1 [CRITICAL] 变量名不能以下划线或美元符号开始,也不能以下划线或美元符号结束
2 [MAJOR] 包名全部小写 , 类名使UpperCamelCase形式 , DO/BO/DTO/VO/AO/PO 等 全部大写
3 [CRITICAL] 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格
4 [CRITICAL] 常量命名全部大写,单词间用下划线隔开
5 [CRITICAL] 抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;
6 [MAJOR] 测试类名以目标测试类名为前缀,以 Test 结尾
7 [MAJOR] 数组声明 ,中括号与类型在一起
int[] intArray;
8 [CRITICAL] POJO中布尔类型变量名不要加is前缀,否则部分框架序列化错误
9 [MAJOR] 包名统一使用小写,包名统一使用单数形式,类名可以使用复数形式
com.dyyx.CommUtils
10 [CRITICAL] 接口实现类 在接口类后面加Impl后缀
HelloImpl implements Hello
CacheServiceImpl 实现 CacheService 接口
AbstractTranslator 实现 Translatable 接口
枚举类名加上 Enum 后缀,成员名全部大写,单词间用下划线隔开
枚举是特殊的常量类,且构造方法默认强制私有。
Service/DAO层方法命名规约
1) 获取单个对象的方法用 get 前缀
2) 获取多个对象的方法用 list 前缀
3) 获取统计值的方法用 count 前缀
4) 插入方法用 save/insert 前缀
5) 删除方法用 remove/delete 前缀
6) 修改的方法用 update/modify 前缀
常量定义
1 [MAJOR] 不要使用魔法值
2 [BLOCKER] 在long或者Long赋值时,数值后使用大写的L,小写容易跟数 字 1 搞混
Long a = 2L;
OOP规约
1 [CRITICAL] Object equals方法容易抛空指针异常
"test".equals(object);
推荐使用 java.util.Objects#equals
2 [BLOCKER] 所有包装类对象之间值的比较,全部使用equals方法
3 [MAJOR] 基本数据类型与包装数据类型的使用
POJO 类属性必须使用包装类型
RPC 方法的返回值和参数必须使用包装类型
所有的局部变量使用基本类型
4 [MAJOR] 定义 DO/DTO/VO 等 POJO 类时,不要设置默认值
5 [MAJOR] POJO 类必须写 toString 方法
6 [MAJOR] 字符串拼接,使用 StringBuilder
7 [MAJOR] 避免精度丢失,避免使用 BigDecimal(double) 把 double 转成 BigDecimal
控制语句
1 [CRITICAL] switch块,每个case要么通过continue/break/return等来终止,要么注释说明程序将继续执行到哪一个 case 为止;
switch 块,必须包含一个 default 语句并放在最后
2 [BLOCKER] 在if/else/for/while/do语句中必须使用大括号,即使只有一行代码
if (condition) {statements;}
3 [MAJOR] 不要在条件判断中执行复杂语句,可将复杂逻辑判断的结果赋值给一个有意义的布尔变量名
说明:很多 if 语句内的逻辑表达式相当复杂,与、或、取反混合运算,甚至各种方法纵深调用,理解成 本非常高。如果赋值一个非常好理解的布尔变量名字,则是件令人爽心悦目的事情。
4 [Recommended] 避免采用反逻辑运算符 !
取反逻辑不利于快速理解,推荐使用正向逻辑写法
异常处理
1 [CRITICAL] 事务代码 ,catch异常后,如果需要回滚事务,一定要手动回滚事务。
2 [CRITICAL] 不要在finally块中使用return
try 块中的 return 语句执行后,并不马上返回,而是继续执行 finally 块中的语句,
如果此处存 在 return 语句,则在此直接返回,丢弃 try 块中的返回值
3 [MAJOR] 返回类型为基本类型,return 包装数据类型时,自动拆箱有可能产生 NPE
public int xxx() { return Integer对象;} 可能 NPE
代码注释
1 [MAJOR] 类、类属性、类方法的注释必须使用Javadoc规范,使用/**内容*/格式,不得使用 // xxx 方式。
2 [MAJOR] 所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。
对子类的实现要求,或者调用注意事项,请一并说明。
3 [MAJOR] 所有的类都必须添加创建者和创建日期。
4 [MAJOR] 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释 使用/* */注释,注意与代码对齐。
5 [CRITICAL] 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
代码格式
1 [MAJOR] 单个方法的总行数不超过 80 行
除注释之外的方法签名、左右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过 80 行
其他
1 [MAJOR] 避免用Apache Beanutils进行属性copy
Apache BeanUtils性能较差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。
2 [BLOCKER] 使用正则表达式时,利用预编译功能
不要在方法体内定义:Pattern pattern = Pattern.compile("xxx");
3 [BLOCKER] 后台输送给页面的变量 $!{var} 注意加上感叹号
4 [MAJOR] Math.random() 返回 double 类型,取值范围[0,1) (可能为0,注意除零异常)
获取整数类型随机数,使用 Random 对象的 nextInt 或者 nextLong 方法
5 [BLOCKER] 获取当前毫秒数 System.currentTimeMillis(); 不要使用 new Date().getTime();
获取更加精确的纳秒级时间 使用 System.nanoTime()
6 [CRITICAL] 日期格式化格式
yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year (JDK7 之后引入),
当天所在的周属于的年份,一周从周日开始,周六结束, 只要本周跨年,返回的 YYYY 就是下一年
表示月份是大写的 M
表示分钟则是小写的 m
24 小时制的是大写的 H
12 小时制的则是小写的 h
SSS 毫秒
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
yyyy-MM-dd HH:mm:ss.SSS
7 [MAJOR] 及时清理不再使用的代码或配置信息
上一篇
下一篇
不要在finally块中使用return
jcmd PerfCounter 说明
集合遍历删除注意点
jvm热点线程定位
并发编程模型
slf4j为什么用{}而不是%s