每个项目必须拥有三个功能模块,分别为api、client、provider三个功能包。依赖关系图:
正例:startTime / workQueue / nameList / TERMINATED_THREAD_COUNT
反例:startedAt / QueueOfWork / listName / COUNT_TERMINATED_THREAD
说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:public class OrderFactory; public class LoginProxy; public class ResourceObserver;
说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS / UNKNOWN_REASON。
说明:如果存在名称之外的延伸属性应使用enum类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。
说明:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。
正例:"test".equals(object); 反例:object.equals("test");
说明:推荐使用java.util.Objects#equals(JDK7引入的工具类)。
说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数。
正例1:指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。
正例2:使用BigDecimal来定义值,再进行浮点数的运算操作。
正例:数据库字段的bigint必须与类属性的Long类型相对应。
说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。正例:优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = BigDecimal.valueOf(0.1);
说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为承载的信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。
说明:下例中,反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象作为Map的键,那么必须复写hashCode和equals。
说明:String因为重写了hashCode和equals方法,所以我们可以愉快地使用String对象作为key来使用。
说明:前者的时间复杂度为O(1),而且可读性更好。
说明:菱形泛型,即diamond,直接使用<>来指代前边已经指定的类型。
// diamond方式,即<>
HashMap<String, String> userCache = new HashMap<>(16);
// 全省略方式
ArrayList<User> users = new ArrayList(10);
说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.forEach方法。
集合类 | Key | Value | Super | 说明 |
Hashtable | Not null | Not null | Dictionary | 线程安全 |
ConcurrentHashMap | Not null | Not null | AbstractMap | 锁分段技术(CAS) |
TreeMap | Not null | 允许为null | AbstractMap | 线程不安全 |
HashMap | Not null | 允许为null | AbstractMap | 线程不安全 |
说明:Executors返回的线程池对象的弊端如下:
1、FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2、CachedThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
说明:因为String字符串的拼接会使用StringBuilder的append()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。
正例:打印日志时仅打印出业务相关属性值或者调用其对象的toString()方法。