Java优雅编码
让代码性能更高
- 需要 Map 的主键和取值时,应该迭代 entrySet()
- 应该使用Collection.isEmpty()检测空
- 不要把集合对象传给自己
- 集合初始化尽量指定大小
- 字符串拼接使用 StringBuilder
- 判断链表还是数组
- 频繁调用 Collection.contains 方法请使用 Set
- 直接赋值常量值,禁止声明新对象
- 当成员变量值无需改变时,尽量定义为静态常量
- 尽量使用基本数据类型,避免自动装箱和拆箱
- 如果变量的初值会被覆盖,就没有必要给变量赋初值
- 尽量使用函数内的基本类型临时变量
- 尽量不要在循环体外定义变量
- 不可变的静态常量,尽量使用非线程安全类
- 尽量避免定义不必要的子类
- 尽量指定类的final修饰符
- 把跟类成员变量无关的方法声明成静态方法
- 尽量使用基本数据类型作为方法参数类型,避免不必要的装箱、拆箱和空指针判断
- 协议方法参数值非空,避免不必要的空指针判断
- 尽量避免不必要的函数封装
- 尽量减少方法的重复调用
- 尽量使用移位来代替正整数乘除
- 尽量不在条件表达式中使用!取反
- 对于多常量选择分支,尽量使用switch语句而不是if-else语句
- 尽量不要使用正则表达式匹配
- 不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组
- 集合转化为类型T数组时,尽量传入空数组T[0]
- 不要使用循环拷贝集合,尽量使用JDK提供的方法拷贝集合
- 尽量重复使用同一缓冲区
- 尽量使用缓冲流减少IO操作
- 在单线程中,尽量使用非线程安全类
- 在多线程中,尽量使用线程安全类
- 尽量减少同步代码块范围
- 尽量使用线程池减少线程开销
让代码更优雅 - 长整型常量后添加大写 L
- 不要使用魔法值
- 不要使用集合实现来赋值静态成员变量
- 建议使用 try-with-resources 语句
- 删除未使用的方法、参数、变量
- 公有静态常量应该通过类访问
- 使用String.valueOf(value)代替""+value
- 过时代码添加 @Deprecated 注解
- 尽量避免在循环中捕获异常
让代码远离 bug - 禁止使用构造方法 BigDecimal(double)
- 返回空数组和空集合而不是 null
- 优先使用常量或确定值来调用 equals 方法
- 枚举的属性字段必须是私有不可变
- 小心String.split(String regex)
让代码性能更高 - 需要 Map 的主键和取值时,应该迭代 entrySet()
反例:
Map<String, String> map = …;
for (String key : map.keySet()) {
String value = map.get(key);
…
}
1
2
3
4
5
正例
Map<String, String> map = …;
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
…
}
1
2
3
4
5
6
2. 应该使用Collection.isEmpty()检测空
反例:
if (collection.size() == 0) {
…
}
1
2
3
正例:
if (collection.isEmpty()) {
…
}
1
2
3
如果需要还需要检测 null ,可采用CollectionUtils.isEmpty(collection)和CollectionUtils.isNotEmpty(collection)。
- 不要把集合对象传给自己
反例:
List list = new ArrayList<>();
list.add(“Hello”);
list.add(“World”);
if (list.containsAll(list)) { // 无意义,总是返回true
…
}
list.removeAll(list); // 性能差, 直接使用clear()
1
2
3
4
5
6
7
4. 集合初始化尽量指定大小
Java集合初始化时都会指定一个默认大小,当默认大小不再满足数据需求时就会扩容,每次扩容的时间复杂度有可能是O(n)
反例:
List userDOList = …;
Set userSet = new HashSet<>();
Map<Long, UserDO> userMap = new HashMap<>();
List userList = new ArrayList<>();
for (UserDO userDO : userDOList) {
userSet.add(userDO.getId());
userMap.put(userDO.getId(), userDO);
userList.add(transUser(userDO));
}
1
2
3
4
5
6
7
8
9
正例:
List userDOList = …;
int userSize = userDOList.size();
Set userSet = new HashSet<>(userSize);
Map<Long, UserDO> userMap = new HashMap<>((int) Math.ceil(userSize * 4.0 / 3));
List userList = new ArrayList<>(userSize);
for (UserDO userDO : userDOList) {
userSet.add(userDO.getId());
userMap.put(userDO.getId(), userDO);
userList.add(transUser(userDO));
}
1
2
3
4
5
6
7
8
9
10
5. 字符串拼接使用 StringBuilder
反例:
String s = “”;
for (int i = 0; i < 10; i++) {
s += i;
}
1
2
3
4
正例:
String a = “a”;
String b = “b”;
String c = “c”;
String s = a + b + c; // 没问题,java编译器会进行优化
StringBuilder sb = new StringBuilder(50); //尽量设置初始化大小
for (int i = 0; i < 10; i++) {
sb.append(i);
}
1
2
3
4
5
6
7
8
6. 判断链表还是数组
正例:
// 调用别人的服务获取到list
List list = otherService.getList();
if (list instanceof RandomAccess) {
// 内部数组实现,可以随机访问
System.out.println(list.get(list.size() - 1));
} else {
// 内部可能是链表实现,随机访问效率低
}
1
2
3
4
5
6
7
8
7. 频繁调用 Collection.contains 方法请使用 Set
反例:
ArrayList list = otherService.getList();
for (int i = 0; i <= Integer.MAX_VALUE; i++) {
// 时间复杂度O(n)
list.contains(i);
}
1
2
3
4
5
正例:
ArrayList list = otherService.getList();
Set set = new HashSet(list);
for (int i = 0; i <= Integer.MAX_VALUE; i++) {
// 时间复杂度O(1)
set.contains(i);
}
1
2
3
4
5
6
8. 直接赋值常量值,禁止声明新对象
直接赋值常量值,只是创建了一个对象引用,而这个对象引用指向常量值。
反例:
Long i = new Long(1L);
String s = new String(“abc”);
1
2
正例:
Long i = 1L;
String s = “abc”;
1
2
9. 当成员变量值无需改变时,尽量定义为静态常量
在类的每个对象实例中,每个成员变量都有一份副本,而成员静态常量只有一份实例
反例:
public class HttpConnection {
private final long timeout = 5L;
…
}
1
2
3
4
正例:
public class HttpConnection {
private static final long TIMEOUT = 5L;
…
}
1
2
3
4
5
10. 尽量使用基本数据类型,避免自动装箱和拆箱
装箱和拆箱都是需要CPU和内存资源的,所以应尽量避免使用自动装箱和拆箱
反例:
Integer sum = 0;
int[] values = …;
for (int value : values) {
sum += value; // 相当于result = Integer.valueOf(result.intValue() + value);
}
1
2
3
4
5
正例:
int sum = 0;
int[] values = …;
for (int value : values) {
sum += value;
}
1
2
3
4
5
11. 如果变量的初值会被覆盖,就没有必要给变量赋初值
反例:
List userList = new ArrayList<>();
if (isAll) {
userList = userDAO.queryAll();
} else {
userList = userDAO.queryActive();
}
1
2
3
4
5
6
正例:
List userList;
if (isAll) {
userList = userDAO.queryAll();
} else {
userList = userDAO.queryActive();
}
1
2
3
4
5
6
12. 尽量使用函数内的基本类型临时变量
在函数内,基本类型的参数和临时变量都保存在栈(Stack)中,访问速度较快;对象类型的参数和临时变量的引用都保存在栈(Stack)中,内容都保存在堆(Heap)中,访问速度较慢。在类中,任何类型的成员变量都保存在堆(Heap)中,访问速度较慢
反例:
public final class Accumulator {
private double result = 0.0D;
public void addAll(@NonNull double[] values) {
for(double value : values) {
result += value;
}
}
…
}
1
2
3
4
5
6
7
8
9
正例:
public final class Accumulator {
private double result = 0.0D;
public void addAll(@NonNull double[] values) {
double sum = 0.0D;
for(double value : values) {
sum += value;
}
result += sum;
}
…
}
1
2
3
4
5
6
7
8
9
10
11
13. 尽量不要在循环体外定义变量
在老版JDK中,建议“尽量不要在循环体内定义变量”,但是在新版的JDK中已经做了优化,根据“ 局部变量作用域最小化 ”原则,变量定义在循环体内更科学更便于维护,避免了延长大对象生命周期导致延缓回收问题
反例:
UserVO userVO;
List userDOList = …;
List userVOList = new ArrayList<>(userDOList.size());
for (UserDO userDO : userDOList) {
userVO = new UserVO();
userVO.setId(userDO.getId());
…
userVOList.add(userVO);
}
1
2
3
4
5
6
7
8
9
正例:
List userDOList = …;
List userVOList = new ArrayList<>(userDOList.size());
for (UserDO userDO : userDOList) {
UserVO userVO = new UserVO();
userVO.setId(userDO.getId());
…
userVOList.add(userVO);
}
1
2
3
4
5
6
7
8
14. 不可变的静态常量,尽量使用非线程安全类
反例:
public static final Map<String, Class> CLASS_MAP;
static {
Map<String, Class> classMap = new ConcurrentHashMap<>(16);
classMap.put(“VARCHAR”, java.lang.String.class);
…
CLASS_MAP = Collections.unmodifiableMap(classMap);
}
1
2
3
4
5
6
7
正例:
public static final Map<String, Class> CLASS_MAP;
static {
Map<String, Class> classMap = new HashMap<>(16);
classMap.put(“VARCHAR”, java.lang.String.class);
…
CLASS_MAP = Collections.unmodifiableMap(classMap);
}
1
2
3
4
5
6
7
15. 尽量避免定义不必要的子类
多一个类就需要多一份类加载,所以尽量避免定义不必要的子类
反例:
public static final Map<String, Class> CLASS_MAP =
Collections.unmodifiableMap(new HashMap<String, Class>(16) {
private static final long serialVersionUID = 1L;
{
put(“VARCHAR”, java.lang.String.class);
}
});
1
2
3
4
5
6
7
正例:
public static final Map<String, Class> CLASS_MAP;
static {
Map<String, Class> classMap = new HashMap<>(16);
classMap.put(“VARCHAR”, java.lang.String.class);
…
CLASS_MAP = Collections.unmodifiableMap(classMap);
}
1
2
3
4
5
6
7
16. 尽量指定类的final修饰符
为类指定final修饰符,可以让该类不可以被继承。如果指定了一个类为final,则该类所有的方法都是final的,Java编译器会寻找机会内联所有的final方法
反例:
public class DateHelper {
…
}
1
2
3
正例:
public final class DateHelper {
…
}
1
2
3
17. 把跟类成员变量无关的方法声明成静态方法
静态方法的好处就是不用生成类的实例就可以直接调用。静态方法不再属于某个对象,而是属于它所在的类
反例:
public int getMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.get(Calendar.MONTH) + 1;
}
1
2
3
4
5
正例:
public static int getMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.get(Calendar.MONTH) + 1;
}
1
2
3
4
5
18. 尽量使用基本数据类型作为方法参数类型,避免不必要的装箱、拆箱和空指针判断
反例:
public static double sum(Double value1, Double value2) {
double double1 = Objects.isNull(value1) ? 0.0D : value1;
double double2 = Objects.isNull(value2) ? 0.0D : value2;
return double1 + double2;
}
double result = sum(1.0D, 2.0D);
1
2
3
4
5
6
正例:
public static double sum(double value1, double value2) {
return value1 + value2;
}
double result = sum(1.0D, 2.0D);
1
2
3
4
19. 协议方法参数值非空,避免不必要的空指针判断
协议编程,可以@NonNull和@Nullable标注参数
反例:
public static boolean isValid(UserDO user) {
if (Objects.isNull(user)) {
return false;
}
return Boolean.TRUE.equals(user.getIsValid());
}
1
2
3
4
5
6
正例:
public static boolean isValid(@NonNull UserDO user) {
return Boolean.TRUE.equals(user.getIsValid());
}
1
2
3
20. 尽量避免不必要的函数封装
方法调用会引起入栈和出栈,导致消耗更多的CPU和内存,应当尽量避免不必要的函数封装。当然,为了使代码更简洁、更清晰、更易维护,增加一定的方法调用所带来的性能损耗是值得的
反例:
// 函数封装
public static boolean isVip(Boolean isVip) {
return Boolean.TRUE.equals(isVip);
}
// 使用代码
boolean isVip = isVip(user.getVip());
1
2
3
4
5
6
正例:
boolean isVip = Boolean.TRUE.equals(user.getVip());
1
21. 尽量减少方法的重复调用
反例:
List userList = …;
for (int i = 0; i < userList.size(); i++) {
…
}
1
2
3
4
正例:
List userList = …;
int userLength = userList.size();
for (int i = 0; i < userLength; i++) {
…
}
1
2
3
4
5
22. 尽量使用移位来代替正整数乘除
用移位操作可以极大地提高性能。对于乘除2^n(n为正整数)的正整数计算,可以用移位操作来代替
反例:
int num1 = a * 4;
int num2 = a / 4;
1
2
正例:
int num1 = a << 2;
int num2 = a >> 2;
1
2
23. 尽量不在条件表达式中使用!取反
使用!取反会多一次计算,如果没有必要则优化掉
反例:
if (!(a >= 10)) {
… // 条件处理1
} else {
… // 条件处理2
}
1
2
3
4
5
正例:
if (a < 10) {
… // 条件处理1
} else {
… // 条件处理2
}
1
2
3
4
5
24. 对于多常量选择分支,尽量使用switch语句而不是if-else语句
if-else语句,每个if条件语句都要加装计算,直到if条件语句为true为止。switch语句进行了跳转优化,Java中采用tableswitch或lookupswitch指令实现,对于多常量选择分支处理效率更高。经过试验证明:在每个分支出现概率相同的情况下,低于5个分支时if-else语句效率更高,高于5个分支时switch语句效率更高
反例:
if (i == 1) {
…; // 分支1
} else if (i == 2) {
…; // 分支2
} else if (i == …) {
…; // 分支n
} else {
…; // 分支n+1
}
1
2
3
4
5
6
7
8
9
正例:
if (i == 1) {
…; // 分支1
} else if (i == 2) {
…; // 分支2
} else if (i == …) {
…; // 分支n
} else {
…; // 分支n+1
}
1
2
3
4
5
6
7
8
9
25. 尽量不要使用正则表达式匹配
正则表达式匹配效率较低,尽量使用字符串匹配操作
反例:
String source = “a::1,b::2,c::3,d::4”;
String target = source.replaceAll("::", “=”);
Stringp[] targets = source.spit(":😊;
1
2
3
正例:
String source = “a::1,b::2,c::3,d::4”;
String target = source.replace("::", “=”);
Stringp[] targets = StringUtils.split(source, “::”);
1
2
3
26. 不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组
推荐使用System.arraycopy拷贝数组,也可以使用Arrays.copyOf拷贝数组
反例:
int[] sources = new int[] {1, 2, 3, 4, 5};
int[] targets = new int[sources.length];
for (int i = 0; i < targets.length; i++) {
targets[i] = sources[i];
}
1
2
3
4
5
正例:
int[] sources = new int[] {1, 2, 3, 4, 5};
int[] targets = new int[sources.length];
System.arraycopy(sources, 0, targets, 0, targets.length);
1
2
3
27. 集合转化为类型T数组时,尽量传入空数组T[0]
将集合转换为数组有2种形式:toArray(new T[n])和toArray(new T[0])。在旧的Java版本中,建议使用toArray(new T[n]),因为创建数组时所需的反射调用非常慢。在OpenJDK6后,反射调用是内在的,使得性能得以提高,toArray(new T[0])比toArray(new T[n])效率更高。此外,toArray(new T[n])比toArray(new T[0])多获取一次列表大小,如果计算列表大小耗时过长,也会导致toArray(new T[n])效率降低
反例:
List integerList = Arrays.asList(1, 2, 3, 4, 5, …);
Integer[] integers = integerList.toArray(new Integer[integerList.size()]);
1
2
正例:
List integerList = Arrays.asList(1, 2, 3, 4, 5, …);
Integer[] integers = integerList.toArray(new Integer[0]); // 勿用new Integer[]{}
1
2
28. 不要使用循环拷贝集合,尽量使用JDK提供的方法拷贝集合
JDK提供的方法可以一步指定集合的容量,避免多次扩容浪费时间和空间。同时,这些方法的底层也是调用System.arraycopy方法实现,进行数据的批量拷贝效率更高
反例:
List user1List = …;
List user2List = …;
List userList = new ArrayList<>(user1List.size() + user2List.size());
for (UserDO user1 : user1List) {
userList.add(user1);
}
for (UserDO user2 : user2List) {
userList.add(user2);
}
1
2
3
4
5
6
7
8
9
正例:
List user1List = …;
List user2List = …;
List userList = new ArrayList<>(user1List.size() + user2List.size());
userList.addAll(user1List);
userList.addAll(user2List);
1
2
3
4
5
29. 尽量重复使用同一缓冲区
针对缓冲区,Java虚拟机需要花时间生成对象,还要花时间进行垃圾回收处理。所以,尽量重复利用缓冲区
反例:
StringBuilder builder1 = new StringBuilder(128);
builder1.append(“update t_user set name = '”).append(userName).append("’ where id = ").append(userId);
statement.executeUpdate(builder1.toString());
StringBuilder builder2 = new StringBuilder(128);
builder2.append("select id, name from t_user where id = ").append(userId);
ResultSet resultSet = statement.executeQuery(builder2.toString());
…
1
2
3
4
5
6
7
正例:
StringBuilder builder = new StringBuilder(128);
builder.append(“update t_user set name = '”).append(userName).append("’ where id = ").append(userId);
statement.executeUpdate(builder.toString());
builder.setLength(0);
builder.append("select id, name from t_user where id = ").append(userId);
ResultSet resultSet = statement.executeQuery(builder.toString());
…
1
2
3
4
5
6
7
30. 尽量使用缓冲流减少IO操作
使用缓冲流BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream等,可以大幅较少IO次数并提升IO速度
反例:
try (FileInputStream input = new FileInputStream(“a”);
FileOutputStream output = new FileOutputStream(“b”)) {
int size = 0;
byte[] temp = new byte[1024];
while ((size = input.read(temp)) != -1) {
output.write(temp, 0, size);
}
} catch (IOException e) {
log.error(“复制文件异常”, e);
}
1
2
3
4
5
6
7
8
9
10
正例:
try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(“a”));
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(“b”))) {
int size = 0;
byte[] temp = new byte[1024];
while ((size = input.read(temp)) != -1) {
output.write(temp, 0, size);
}
} catch (IOException e) {
log.error(“复制文件异常”, e);
}
1
2
3
4
5
6
7
8
9
10
31. 在单线程中,尽量使用非线程安全类
反例:
StringBuffer buffer = new StringBuffer(128);
buffer.append(“select * from “).append(T_USER).append(” where id = ?”);
1
2
正例:
StringBuilder buffer = new StringBuilder(128);
buffer.append(“select * from “).append(T_USER).append(” where id = ?”);
1
2
31. 在多线程中,尽量使用线程安全类
反例:
private volatile int counter = 0;
public void access(Long userId) {
synchronized (this) {
counter++;
}
…
}
1
2
3
4
5
6
7
正例:
private final AtomicInteger counter = new AtomicInteger(0);
public void access(Long userId) {
counter.incrementAndGet();
…
}
1
2
3
4
5
32. 尽量减少同步代码块范围
在一个方法中,可能只有一小部分的逻辑是需要同步控制的,如果同步控制了整个方法会影响执行效率。所以,尽量减少同步代码块的范围,只对需要进行同步的代码进行同步
反例:
private volatile int counter = 0;
public synchronized void access(Long userId) {
counter++;
… // 非同步操作
}
1
2
3
4
5
正例:
private volatile int counter = 0;
public void access(Long userId) {
synchronized (this) {
counter++;
}
… // 非同步操作
}
1
2
3
4
5
6
7
33. 尽量使用线程池减少线程开销
多线程中两个必要的开销:线程的创建和上下文切换。采用线程池,可以尽量地避免这些开销
反例:
public void executeTask(Runnable runnable) {
new Thread(runnable).start();
}
1
2
3
正例:
private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(10);
public void executeTask(Runnable runnable) {
executorService.execute(runnable);
}
1
2
3
4
让代码更优雅
- 长整型常量后添加大写 L
反例:
long value = 1l;
long max = Math.max(1L, 5);
1
2
正例:
long value = 1L;
long max = Math.max(1L, 5L);
1
2
2. 不要使用魔法值
反例:
for (int i = 0; i < 100; i++){
…
}
if (a == 100) {
…
}
1
2
3
4
5
6
正例:
private static final int MAX_COUNT = 100;
for (int i = 0; i < MAX_COUNT; i++){
…
}
if (count == MAX_COUNT) {
…
}
1
2
3
4
5
6
7
3. 不要使用集合实现来赋值静态成员变量
反例:
private static Map<String, Integer> map = new HashMap<String, Integer>() {
{
put(“a”, 1);
put(“b”, 2);
}
};
private static List list = new ArrayList() {
{
add(“a”);
add(“b”);
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
正例:
private static Map<String, Integer> map = new HashMap<>();
static {
map.put(“a”, 1);
map.put(“b”, 2);
};
private static List list = new ArrayList<>();
static {
list.add(“a”);
list.add(“b”);
};
1
2
3
4
5
6
7
8
9
10
11
4. 建议使用 try-with-resources 语句
反例:
private void handle(String fileName) {
BufferedReader reader = null;
try {
String line;
reader = new BufferedReader(new FileReader(fileName));
while ((line = reader.readLine()) != null) {
…
}
} catch (Exception e) {
…
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
…
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
正例:
private void handle(String fileName) {
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = reader.readLine()) != null) {
…
}
} catch (Exception e) {
…
}
}
1
2
3
4
5
6
7
8
9
10
5. 删除未使用的方法、参数、变量
反例:
public class DoubleDemo1 {
private int unusedField = 100;
private void unusedMethod() {
…
}
public int sum(int a, int d, int d) {
int c = 100;
return a + b;
}
}
1
2
3
4
5
6
7
8
9
10
正例:
public class DoubleDemo1 {
public int sum(int a, int b) {
return a + b;
}
}
1
2
3
4
5
6. 公有静态常量应该通过类访问
反例:
public class User {
public static final String CONST_NAME = “name”;
…
}
User user = new User();
String nameKey = user.CONST_NAME;
1
2
3
4
5
6
7
正例:
public class User {
public static final String CONST_NAME = “name”;
…
}
String nameKey = User.CONST_NAME;
1
2
3
4
5
6
7. 使用String.valueOf(value)代替""+value
反例:
int i = 1;
String s = “” + i;
1
2
正例:
int i = 1;
String s = String.valueOf(i);
1
2
8. 过时代码添加 @Deprecated 注解
正例:
/**
- @deprecated 此方法效率较低,请使用{@link newSave()}方法替换它
*/
@Deprecated
public void save(){
// do something
}
1
2
3
4
5
6
7
- 尽量避免在循环中捕获异常
反例:
public Double sum(List valueList) {
double sum = 0.0D;
for (String value : valueList) {
try {
sum += Double.parseDouble(value);
} catch (NumberFormatException e) {
return null;
}
}
return sum;
}
1
2
3
4
5
6
7
8
9
10
11
正例:
public Double sum(List valueList) {
double sum = 0.0D;
try {
for (String value : valueList) {
sum += Double.parseDouble(value);
}
} catch (NumberFormatException e) {
return null;
}
return sum;
}
1
2
3
4
5
6
7
8
9
10
11
让代码远离 bug
- 禁止使用构造方法 BigDecimal(double)
反例:
BigDecimal value = new BigDecimal(0.1D); // 0.100000000000000005551115…
1
正例:
BigDecimal value = BigDecimal.valueOf(0.1D);; // 0.1
1
2. 返回空数组和空集合而不是 null
反例:
public static Result[] getResults() {
return null;
}
public static List getResultList() {
return null;
}
public static Map<String, Result> getResultMap() {
return null;
}
public static void main(String[] args) {
Result[] results = getResults();
if (results != null) {
for (Result result : results) {
…
}
}
List<Result> resultList = getResultList();
if (resultList != null) {
for (Result result : resultList) {
...
}
}
Map<String, Result> resultMap = getResultMap();
if (resultMap != null) {
for (Map.Entry<String, Result> resultEntry : resultMap) {
...
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
正例:
public static Result[] getResults() {
return new Result[0];
}
public static List getResultList() {
return Collections.emptyList();
}
public static Map<String, Result> getResultMap() {
return Collections.emptyMap();
}
public static void main(String[] args) {
Result[] results = getResults();
for (Result result : results) {
…
}
List<Result> resultList = getResultList();
for (Result result : resultList) {
...
}
Map<String, Result> resultMap = getResultMap();
for (Map.Entry<String, Result> resultEntry : resultMap) {
...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3. 优先使用常量或确定值来调用 equals 方法
反例:
public void isFinished(OrderStatus status) {
return status.equals(OrderStatus.FINISHED); // 可能抛空指针异常
}
1
2
3
正例:
public void isFinished(OrderStatus status) {
return OrderStatus.FINISHED.equals(status);
}
public void isFinished(OrderStatus status) {
return Objects.equals(status, OrderStatus.FINISHED);
}
1
2
3
4
5
6
7
4. 枚举的属性字段必须是私有不可变
反例:
public enum UserStatus {
DISABLED(0, “禁用”),
ENABLED(1, “启用”);
public int value;
private String description;
private UserStatus(int value, String description) {
this.value = value;
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
正例:
public enum UserStatus {
DISABLED(0, “禁用”),
ENABLED(1, “启用”);
private final int value;
private final String description;
private UserStatus(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public String getDescription() {
return description;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
5. 小心String.split(String regex)
反例:
“a.ab.abc”.split("."); // 结果为[]
“a|ab|abc”.split("|"); // 结果为[“a”, “|”, “a”, “b”, “|”, “a”, “b”, “c”]
1
2
正例:
“a.ab.abc”.split("\."); // 结果为[“a”, “ab”, “abc”]
“a|ab|abc”.split("\|"); // 结果为[“a”, “ab”, “abc”]
————————————————
版权声明:本文为优快云博主「季雨风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/jichao138168/article/details/103609318