Java开发手册-----读ali

一、命名规范

1、【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

 正例:MAX_STOCK_COUNT

 反例:MAX_COUNT

2、【强制】抽象类命名使用Abstract或Base开头

      异常类命名使用Exception结尾

      测试类命名以它要测试的类的名称开始,以Test结尾

3、【强制】中括号是数组类型的一部分,数组定义如下:String[ ] args; 

   反例:使用String args[ ] 的方式来定义。

4、【强制】POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。

 反例:定义为基本数据类型Boolean isDeleted;的属性,它的方法也是isDeleted(),RPC框架在反向解析的时候,

 “以为”对应的属性名称是deleted导致属性获取不到,进而抛出异常。

5、【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。

      包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。

        正例: 应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考spring的框架结构)

6、【参考】各层命名规约: A) Service/DAO层方法命名规约 

1) 获取单个对象的方法用get做前缀。

  2) 获取多个对象的方法用list做前缀。

  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。

二、常量定义

1、【强制】long或者Long初始赋值时,使用大写的L,不能是小写的l

     小写容易跟数字1混淆,造成误解。 

     说明:Long a = 2l; 写的是数字的21,还是Long型的2?

2、【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。

     说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
     正例:缓存相关常量放在类CacheConsts下;系统配置相关常量放在类ConfigConsts下。

三、代码格式

1、【强制】大括号的使用约定。

      如果是大括号内为空,则简洁地写成{}即可,不需要换行

      如果是非空代码块则: 1) 左大括号前不换行。 2) 左大括号后换行。 3) 右大括号前换行。 

4) 右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。

2、【强制】if / for / while / switch / do 等保留字与括号之间都必须加空格。

3、【强制】任何二目、三目运算符的左右两边都需要加一个空格。 说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。

4、【强制】单行字符数限不超过 120 个,超出需要换行时 个,超出需要换行时 遵循如下原则:

  1) 第二行相对一缩进 4个空格,从第三行开始不再继续缩进参考示例。 

2) 运算符与下文一起换行

  3) 方法调用的点符号与下文一起换行

  4) 方法调用时,多个参数,需要换行时,在逗号后进行

  5) 在括号前不要换行,见反例。 

正例:StringBuffer sb = new StringBuffer();
// 超过120个字符的情况下,换行缩进4个空格,点号和方法名称一起换行
  sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");
反例:StringBuffer sb = new StringBuffer();
// 超过120个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
("huang");
// 参数很多的方法调用可能超过120个字符,不要在逗号前换行
method(args1, args2, args3, ...
, argsX);

5、【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。 正例:下例中实参的"a",后边必须要有一个空格。
 method("a", "b", "c");

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

7、接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。

8、【强制】Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。 

正例:"test".equals(object); 

反例:object.equals("test");

9、【强制】所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较

10、【推荐】所有的局部变量使用基本数据类型。

11、正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。

12、【强制】定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。 

反例:POJO类的gmtCreate默认值为new Date();但是这个属性在数据提取时并没有置入具体值,

   在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

13、【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中

14、【推荐】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展

四、集合处理

1、【强制】使用集合转数组的方法,必须使用集合的toArray(T[ ] array),传入的是类型完全一样的数组,大小就是list.size()。
     说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;

     如果数组元素大于实际所需,下标为 [ list.size() ] 的数组元素将被置为null,其它数组元素保持原值,

 因此最好将方法入参数组大小定义与集合元素个数一致。 正例:
                         List<String> list = new ArrayList<String>(2);
                        list.add("guan");
list.add("bao");
String[ ] array = new String[list.size()];
array = list.toArray(array);

2、【强制】使用工具类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)也会随之修改。

3、使用entrySet遍历Map类集合KV;JDK8,使用Map.foreach方法




4、【参考】利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。

五、并发处理

1、【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。 正例:
public class TimerTaskThread extends Thread {
public TimerTaskThread() {
super.setName("TimerTaskThread");
...
}


2、【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程

3、【强制】线程池不允许使用 【强制】线程池不允许使用 Executors去创建,而是通过 去创建,而是通过 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的方式,这样 的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。 说明: Executors 返回的线程池对象 返回的线程池对象 的弊端 如下 :

 1)FixedThreadPool FixedThreadPool 和 SingleThreadPoolPool: 

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

 2)CachedThreadPool 和 ScheduledThreadPool : 

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

4、【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。

  正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}

};
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,

官方给出的解释:simple beautiful strong immutable thread-safe。

5、【强制】高并发时,同步调用应该去考量锁的性能损耗。

能用无锁数据结构,就不要用锁;

锁区块,就不要锁整个方法体;

能用对象锁,就不要用类锁。 

说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用RPC方法。

6、【强制】对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。

说明:线程一需要对表A、B、C依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序也必须是A、B、C,否则可能出现死锁。

7、【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值