1.【推荐】不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。如:缓存相关的常量放在类:CacheConsts下;系统配置相关的常量放在类:ConfigConsts下。 说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
2.【参考】枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。 说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。 正例:枚举名字:DealStatusEnum,成员名称:SUCCESS / UNKOWN_REASON。
枚举其实就是个普通的类,类中存放着N个常量和方法,不过和普通的类不同的是:枚举类唯一集成了java.lang.Enum,所以限制了只能在枚举范围内取值(java是单一继承)
3.【推荐】如果变量值仅在一个范围内变化用Enum类。如果还带有名称之外的延伸属性,必须使用Enum类,下面正例中的数字就是延伸信息,表示星期几。 正例:public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}
4. 【参考】各层命名规约: 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。
5.【强制】long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。
6. 【强制】所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。 说明:对于Integer var = ?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。
7. 关于基本数据类型与包装数据类型的使用标准如下:1) 【强制】所有的POJO类属性必须使用包装数据类型。2) 【强制】RPC方法的返回值和参数必须使用包装数据类型。3) 【推荐】所有的局部变量使用基本数据类型。 说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。 正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。 反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示:0%,这是不合理的,应该显示成中划线-。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。
理解:用基本数据类型,查出来0可能代表了多种可能,查询实际值为0,查询为null,远程调用失败,异常退出等,引起不必要的麻烦。而封装类型则不会出现这种问题。
8. 【推荐】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。反例:
String str = "start";
for (int I = 0; I < 100; i++) {
str = str + "hello";
}
说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
9.【推荐】下列情况,声明成final会更有提示性: 1)不需要重新赋值的变量,包括类属性、局部变量。 2) 对象参数前加final,表示不允许修改引用的指向。 3)类方法确定不允许被重写。
可以再深入理解下final。
10.【强制】 ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList ; 说明:subList返回的是 ArrayList的内部类 SubList,并不是 ArrayList,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
11.【强制】使用集合转数组的方法,必须使用集合的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);
反例:直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。
使用时看下数组转集合,集合转数组的方法
12.【推荐】使用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值组合集合。
13. 【推荐】高度注意Map类集合K/V能不能存储null值的情况,如下表格:
集合类 | Key | Value | Super | 说明 |
Hashtable | 不允许为null | 不允许为null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为null | 不允许为null | AbstractMap | 分段锁技术 |
TreeMap | 不允许为null | 允许为null | AbstractMap | 线程不安全 |
HashMap | 允许为null | 允许为null | AbstractMap | 线程不安全 |
反例: 由于HashMap的干扰,很多人认为ConcurrentHashMap是可以置入null值,注意存储null值时会抛出NPE异常。
比如别人可能会问hashTable和hashMap的区别
14.【参考】利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。
List newList = new ArrayList(new HashSet(list)); 无序排列
List newList = new ArrayList(new TreeSet(list)); 有序排列(按照字母表顺序)
<--控制语句-->
15.【强制】在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。
16.【推荐】推荐尽量少用else, if-else的方式可以改写成:
if (condition) {
...
return obj;
}
// 接着写else的业务逻辑代码;
说明:如果非得使用if()...else if()...else...方式表达逻辑,【强制】请勿超过3层,超过请使用状态设计模式。
正例:逻辑上超过3层的if-else代码可以使用卫语句,或者状态模式来实现。
卫语句:不加else,if条件成立直接return
未完待续...
以上规范均摘抄自阿里巴巴开发手册,收集了一些自己觉得可能会用到的知识点。