java开发规范总结(基于阿里巴巴开发规范)

一.基础注意

1.属性不能起isDelete(以is开头,有些框架会序列化错误)

2.set里面自定义对象必须重写equal和hashCode方法

3.Map的自定义对象作为key,必须重写equal和hashCode方法

4.集合转数组要用toArray(T[ ] array)带参数的方法,大小是list.size()

5.hashMap<>(16)要设置初始容量为16,不然会影响性能

6.任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。

二.编程并发

1.线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样

的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明: Executors 返回的线程池对象的弊端如下:

1) FixedThreadPool 和 SingleThreadPool :

允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。

2) CachedThreadPool 和 ScheduledThreadPool :

允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。

2.SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为

static ,必须加锁,或者使用 DateUtils 工具类。

正例:注意线程安全,使用 DateUtils 。亦推荐如下处理:

private static final ThreadLocal df = new ThreadLocal() {

@ Override

protected DateFormat initialValue() {

return new SimpleDateFormat("yyyy-MM-dd");

}

};

3.线程一需要对表 A 、 B 、 C 依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序

也必须是 A 、 B 、 C ,否则可能出现死锁

4.使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown

方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行

至 await 方法,直到超时才返回结果。

说明:注意,子线程抛出异常堆栈,不能在主线程 try - catch 到。

5.避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一

seed 导致的性能下降。

说明: Random 实例包括 java . util . Random 的实例或者 Math . random() 的方式。

正例:在 JDK 7 之后,可以直接使用 API ThreadLocalRandom ,而在 JDK 7 之前,需要编码保

证每个线程持有一个实例

6.volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,

但是如果多写,同样无法解决线程安全问题。如果是 count ++操作,使用如下类实现:

AtomicInteger count = new AtomicInteger(); count . addAndGet( 1 ); 如果是 JDK 8,推

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

7.HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在

开发过程中可以使用其它数据结构或加锁来规避此风险

8.ThreadLocal 无法解决共享对象的更新问题, ThreadLocal 对象建议使用 static

修饰。这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享

此静态变量 ,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象 ( 只

要是这个线程内定义的 ) 都可以操控这个变量。

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

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

判断条件来代替。

反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变

成了负数,这样的话,活动无法终止。

三.控制语句

1.表达异常的分支时,少用 if-else 方式 ,这种方式可以改写成:

if (condition) {

...

return obj;

}

// 接着写 else 的业务逻辑代码;

说明:如果非得使用 if()...else if()...else... 方式表达逻辑,【强制】避免后续代码维

护困难,请勿超过 3 层。

正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现

2.除常用方法(如 getXxx/isXxx )等外,不要在条件判断中执行其它复杂的语句,将

复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

说明:很多 if 语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么

样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?

正例:

// 伪代码如下

final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);

if (existed) {

...

}

反例:

if ((file.open(fileName, "w") != null) && (...) || (...)) {

...

}

四.异常处理

1.异常不要用来做流程控制,条件控制。

说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式

要低很多。

2.使用 JDK8 的 Optional 类来防止 NPE 问题

五.日志处理

1.正例: ( 占位符 )

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

2.避免重复打印日志,浪费磁盘空间,务必在 log 4 j . xml 中设置 additivity = false 。

正例:

六.数据库

1.单表行数超过 500 万行或者单表容量超过 2 GB ,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

你可能感兴趣的:(java开发规范总结(基于阿里巴巴开发规范))