前言
参考自: 微信公众号"java3y"中的文章 - 《阿里巴巴 Java开发手册》读后感
都是日常能用的一些规范, 还是很有用处的!
一、Java相关
1.POJO是DO/DTO/BO/VO的统称,禁止命名为xxxPOJO
2.获取多个对象的方法中list作为前缀
3.获取统计值的方法用count作为前缀
4.POJO类中的布尔类型(Boolean)的变量都不要加is前缀,否则部分框架解析会引起序列化错误
如果你的变量名带is的话,比如isActive,框架解析的时候可能就当成active了
5.如果是形容能力的接口名称,取对应的形容词为接口名(通常是-able的形式)
6.不允许任何魔法值(未经预先定义的常量)直接出现在代码中
7.Object的euqals方法容易抛出空指针异常,应使用常量或者有值的对象来调用equals。推荐使用java.util.Objects#equals
工具类
8.所有POJO类的属性全部使用包装数据类型,RPC的返回值和参数必须使用包装数据类型,所有的局部变量都使用基本数据类型。定义VO/DTO/DO等POJO类时,不要设定任何属性的默认值
如果你的类属性使用int这样的基本数据类型,默认值是0。一般情况下该变量没有赋值,一般想表达的是不存在(null),而不是0。
9.构造方法禁止加入任何的业务逻辑,如果初始化逻辑可以放在init方法中。set/get方法也不要增加业务逻辑
如果set/get方法放入业务逻辑,有时候排查问题就变得很麻烦了
10.工具类Arrays.asList()把数组转成List时,不能使用其修改集合的相关方法。比如说add、clear、remove
11.在JDK7以及以上版本中,Comparator要满足三个条件,不然调用Arrays.sort()或者Collections.sort()
会报异常。
11.1x,y 的比较结果和 y,x 的比较结果相反
11.2传递性:x>y并且y>z,那么x一定大于z
11.3对称性:x=y,则 x,z 比较结果和y,z比较结果相同
12.使用entrySet遍历Map类集合K/V,而不是用keySet方式遍历
keySet遍历了两次,一次是转成Iterator对象,一次是从hashMap中取出key所对应的value,如果JDK8可以使用Map.foreach方法
13.线程资源必须由线程池提供,不允许在应用中自行显示创建线程。线程池不允许用Executors创建,通过ThreadPoolExecutor的方式创建,这样的处理方式能够让编写代码的工程师更加明确线程池的运行规则,规避资源耗尽的风险。
14.SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类
如果是JDK8应用,可以使用Instant(针对时间统计等场景)代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat
15.避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed导致性能下降
在JDK7之后,可以直接使用API ThreadLocalRandom,而在JDK7 之前,需要编码保证每个线程持有一个实例。
16.类、类属性、类方法的注释必须使用 Javadoc 规范,使用 /*内容/
格式,不得使用 //xxx
方式
17.所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释,除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。所有的类都必须添加创建者和创建日期。
18.对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码的上方,使用三个斜杠///
来说明注释代码的理由
19.保证单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试之间不能互相调用,也不能依赖执行的先后顺序。
20.高并发服务器建议调小TCP协议的time_await超时时间,调大最大事件句柄数(fd),
1.1值得说明的点
一、不允许任何魔法值(未经预先定义的常量)直接出现在代码中
例子:
ps:我猜是把先常量定义出来,后续引用/修改的时候就很方便了。
二、Object的euqals方法容易抛出空指针异常,应使用常量或者有值的对象来调用equals。推荐使用java.util.Objects#equals
工具类
java.util.Object#equals的源码(已经判断null的情况了)
三、工具类Arrays.asList()把数组转成List时,不能使用其修改集合的相关方法。
因为返回的ArrayList是一个内部类,并没有实现集合的修改方法。后台的数据仍是数组,这里体现的是适配器模式。
四、在JDK7以及以上版本中,Comparator要满足自反性,传递性,对称性,不然调用Arrays.sort()或者Collections.sort()
会报异常。
1) x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。
反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
五、使用entrySet遍历Map类集合K/V,而不是用keySet方式遍历
首先我们来看一下使用keySet是如何遍历HashMap的:
再来看一下entrySet,可以直接拿到key和value,不用再使用get方法来得到value,所以比keySet更加推荐使用!
如果是JDK8的话,推荐直接使用Map.forEach()
就好了,我们也来看看用法:
其实在源码里边我们可以发现,forEach实际上就是封装了entrySet,提供forEach给我们可以更加方便地遍历Map集合
六、SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
有以下的例子可以正确使用SimpleDateFormat:
如果是JDK8应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat。
二、数据库相关
1.表达是否概念的字段,必须使用isxxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)
2.小数类型用decimal,禁止使用float和double。
3.varchar是可变字符串,不预选分配存储空间的话,长度不要超过5000个字符。如果超过则用text,独立一张表,用主键对应,避免影响到其他字段的索引效率。
4.表必备的三个字段:id(类型是unsigned bigint),gmt_create(创建时间),gme_modified(修改时间)
5.字段允许适当冗余,以提高查询性能,但必须考虑数据一致性。冗余的字段必须不是频繁修改的字段,不是varhar超长字段(更不能是text字段)。
6.单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表(如果预计三年都达不到这个数据量,不要在创建表的时候就分库分表!)
7.超过三个表禁止使用join,需要join的字段,数据类型必须保持一致,当多表关联查询时,保证被关联的字段需要有索引!
8.在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,页面搜索严禁左模糊或者全模糊,如果需要则通过搜索引擎来解决。
充分利用好最左前缀匹配特性!
9.利用延迟关联或者子查询优化超多也分场景。
10.如果有全球化需要,均以utf-8编码。如果需要存储表情,选择utf8mb4进行存储。