|
|
@ -92,9 +92,9 @@ cache.put(key, value);
|
|
|
|
类 A 中:public static final String YES = "yes";
|
|
|
|
类 A 中:public static final String YES = "yes";
|
|
|
|
类 B 中:public static final String YES = "y";
|
|
|
|
类 B 中:public static final String YES = "y";
|
|
|
|
A.YES.equals(B.YES),预期是 true,但实际返回为 false,导致线上问题。
|
|
|
|
A.YES.equals(B.YES),预期是 true,但实际返回为 false,导致线上问题。
|
|
|
|
3)子工程内部共享常量:即在当前子工程的 constant 目录下。
|
|
|
|
3)子工程内部共享常量:即在当前子工程的 constant 目录下。
|
|
|
|
4) 包内共享常量:即在当前包下单独的 constant 目录下。
|
|
|
|
4)包内共享常量:即在当前包下单独的 constant 目录下。
|
|
|
|
5) 类内共享常量:直接在类内部 private static final 定义。
|
|
|
|
5)类内共享常量:直接在类内部 private static final 定义。
|
|
|
|
|
|
|
|
|
|
|
|
- 如果变量值仅在一个固定范围内变化用 enum 类型来定义。
|
|
|
|
- 如果变量值仅在一个固定范围内变化用 enum 类型来定义。
|
|
|
|
说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。
|
|
|
|
说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。
|
|
|
@ -119,7 +119,8 @@ public enum SeasonEnum {
|
|
|
|
- 所有的覆写方法,必须加@Override 注解。
|
|
|
|
- 所有的覆写方法,必须加@Override 注解。
|
|
|
|
说明:getObject()与 get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override 可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名(由方法名、参数的类型及**顺序** 确定唯一的方法签名)进行修改,其实现类会马上编译报错。
|
|
|
|
说明:getObject()与 get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override 可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名(由方法名、参数的类型及**顺序** 确定唯一的方法签名)进行修改,其实现类会马上编译报错。
|
|
|
|
|
|
|
|
|
|
|
|
- 相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。 说明:可变参数必须放置在参数列表的最后。(能用数组的就不要使用可变参数编程,可变参数在编译时会被编译成数组类型。可变参数能兼容数组类参数,但是数组类参数却无法兼容可变参数。可变参数类型必须作为参数列表的最后一项,且不能放在定长参数的前面。)
|
|
|
|
- 相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。
|
|
|
|
|
|
|
|
说明:可变参数必须放置在参数列表的最后。(能用数组的就不要使用可变参数编程,可变参数在编译时会被编译成数组类型。可变参数能兼容数组类参数,但是数组类参数却无法兼容可变参数。可变参数类型必须作为参数列表的最后一项,且不能放在定长参数的前面。)
|
|
|
|
正例:public List<User> listUsers(String type, Long... ids) {...}
|
|
|
|
正例:public List<User> listUsers(String type, Long... ids) {...}
|
|
|
|
|
|
|
|
|
|
|
|
- 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
|
|
|
|
- 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
|
|
|
@ -156,7 +157,8 @@ tips:
|
|
|
|
- **构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init() 方法中。**
|
|
|
|
- **构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init() 方法中。**
|
|
|
|
在很多client端的代码中有看到这种编码方式。
|
|
|
|
在很多client端的代码中有看到这种编码方式。
|
|
|
|
|
|
|
|
|
|
|
|
- POJO 类必须写 toString() 方法。使用 IDE 中的工具:source -> generate toString() 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString()。 说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。
|
|
|
|
- POJO 类必须写 toString() 方法。使用 IDE 中的工具:source -> generate toString() 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString()。
|
|
|
|
|
|
|
|
说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。
|
|
|
|
|
|
|
|
|
|
|
|
- 当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
|
|
|
|
- 当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
|
|
|
|
|
|
|
|
|
|
|
@ -217,7 +219,8 @@ array = list.toArray(array);
|
|
|
|
String[] strs = list.toArray(new String[0]);
|
|
|
|
String[] strs = list.toArray(new String[0]);
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear 方法会抛出 UnsupportedOperationException 异常。 说明:asList() 的返回对象是一个 Arrays 的内部类ArrayList(而不是java.util.ArrayList),该内部类 并没有实现集合的修改/删除等方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。
|
|
|
|
- 使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
|
|
|
|
|
|
|
|
说明:asList() 的返回对象是一个 Arrays 的内部类ArrayList(而不是java.util.ArrayList),该内部类 并没有实现集合的修改/删除等方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。
|
|
|
|
```java
|
|
|
|
```java
|
|
|
|
String[] str = new String[] { "you", "wu" };
|
|
|
|
String[] str = new String[] { "you", "wu" };
|
|
|
|
List list = Arrays.asList(str);
|
|
|
|
List list = Arrays.asList(str);
|
|
|
@ -263,7 +266,8 @@ for (String item : list) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 在 JDK7 版本及以上,Comparator 实现类要满足如下三个条件,不然 Arrays.sort(), Collections.sort() 会报 IllegalArgumentException 异常。 说明:三个条件如下 1) x,y 的比较结果和 y,x 的比较结果相反。 2) x>y,y>z,则 x>z。 3) x=y,则 x,z 比较结果和 y,z 比较结果相同。
|
|
|
|
- 在 JDK7 版本及以上,Comparator 实现类要满足如下三个条件,不然 Arrays.sort(), Collections.sort() 会报 IllegalArgumentException 异常。
|
|
|
|
|
|
|
|
说明:三个条件如下 1) x,y 的比较结果和 y,x 的比较结果相反。 2) x>y,y>z,则 x>z。 3) x=y,则 x,z 比较结果和 y,z 比较结果相同。
|
|
|
|
```java
|
|
|
|
```java
|
|
|
|
// 反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
|
|
|
|
// 反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
|
|
|
|
new Comparator<Student>() {
|
|
|
|
new Comparator<Student>() {
|
|
|
@ -444,7 +448,8 @@ public void today() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。 说明:很多 if 语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?
|
|
|
|
- 除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。
|
|
|
|
|
|
|
|
说明:很多 if 语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?
|
|
|
|
```java
|
|
|
|
```java
|
|
|
|
// 正例:
|
|
|
|
// 正例:
|
|
|
|
// 伪代码如下
|
|
|
|
// 伪代码如下
|
|
|
@ -535,7 +540,8 @@ put(elephant, fridge);
|
|
|
|
- 获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
|
|
|
|
- 获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
|
|
|
|
说明:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式。在 JDK8 中, 针对统计时间等场景,推荐使用 Instant 类。
|
|
|
|
说明:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式。在 JDK8 中, 针对统计时间等场景,推荐使用 Instant 类。
|
|
|
|
|
|
|
|
|
|
|
|
- 不要在视图模板中加入任何复杂的逻辑。 说明:根据 MVC 理论,视图的职责是展示,不要抢模型和控制器的活。
|
|
|
|
- 不要在视图模板中加入任何复杂的逻辑。
|
|
|
|
|
|
|
|
说明:根据 MVC 理论,视图的职责是展示,不要抢模型和控制器的活。
|
|
|
|
|
|
|
|
|
|
|
|
- 任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。
|
|
|
|
- 任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。
|
|
|
|
|
|
|
|
|
|
|
@ -550,7 +556,8 @@ put(elephant, fridge);
|
|
|
|
正例:if (obj != null) {...}
|
|
|
|
正例:if (obj != null) {...}
|
|
|
|
反例:try { obj.method(); } catch (NullPointerException e) {…}
|
|
|
|
反例:try { obj.method(); } catch (NullPointerException e) {…}
|
|
|
|
|
|
|
|
|
|
|
|
- 异常不要用来做流程控制,条件控制。 说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
|
|
|
|
- 异常不要用来做流程控制,条件控制。
|
|
|
|
|
|
|
|
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
|
|
|
|
|
|
|
|
|
|
|
|
- catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。 对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
|
|
|
|
- catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。 对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
|
|
|
|
说明:对大段代码进行 try-catch,使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题,这是一种不负责任的表现。
|
|
|
|
说明:对大段代码进行 try-catch,使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题,这是一种不负责任的表现。
|
|
|
@ -589,7 +596,8 @@ put(elephant, fridge);
|
|
|
|
1)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
|
|
|
|
1)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
|
|
|
|
2)如果不加栈信息,只是 new 自定义异常,加入自己的理解的 error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。
|
|
|
|
2)如果不加栈信息,只是 new 自定义异常,加入自己的理解的 error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。
|
|
|
|
|
|
|
|
|
|
|
|
- 避免出现重复的代码(Don’t Repeat Yourself),即 DRY 原则。 说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是组件化。
|
|
|
|
- 避免出现重复的代码(Don’t Repeat Yourself),即 DRY 原则。
|
|
|
|
|
|
|
|
说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是组件化。
|
|
|
|
```java
|
|
|
|
```java
|
|
|
|
// 正例:
|
|
|
|
// 正例:
|
|
|
|
// 一个类中有多个 public 方法,都需要进行数行相同的参数校验操作,这个时候请抽取:
|
|
|
|
// 一个类中有多个 public 方法,都需要进行数行相同的参数校验操作,这个时候请抽取:
|
|
|
|