Java优雅编码 让代码性能更高

本文介绍了多个提升Java代码性能的实践方法,如使用`entrySet()`迭代Map,利用`isEmpty()`检测空集合,避免集合对象传给自己,初始化集合时指定大小,字符串拼接使用`StringBuilder`,根据数据结构选择访问方式,使用Set优化`contains`调用,直接赋值常量,定义静态常量,避免自动装箱拆箱,减少不必要的方法封装,利用移位运算替代乘除,以及在多线程环境中使用线程安全类等。通过遵循这些最佳实践,可以使Java代码运行得更加高效和优雅。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java优雅编码
让代码性能更高

  1. 需要 Map 的主键和取值时,应该迭代 entrySet()
  2. 应该使用Collection.isEmpty()检测空
  3. 不要把集合对象传给自己
  4. 集合初始化尽量指定大小
  5. 字符串拼接使用 StringBuilder
  6. 判断链表还是数组
  7. 频繁调用 Collection.contains 方法请使用 Set
  8. 直接赋值常量值,禁止声明新对象
  9. 当成员变量值无需改变时,尽量定义为静态常量
  10. 尽量使用基本数据类型,避免自动装箱和拆箱
  11. 如果变量的初值会被覆盖,就没有必要给变量赋初值
  12. 尽量使用函数内的基本类型临时变量
  13. 尽量不要在循环体外定义变量
  14. 不可变的静态常量,尽量使用非线程安全类
  15. 尽量避免定义不必要的子类
  16. 尽量指定类的final修饰符
  17. 把跟类成员变量无关的方法声明成静态方法
  18. 尽量使用基本数据类型作为方法参数类型,避免不必要的装箱、拆箱和空指针判断
  19. 协议方法参数值非空,避免不必要的空指针判断
  20. 尽量避免不必要的函数封装
  21. 尽量减少方法的重复调用
  22. 尽量使用移位来代替正整数乘除
  23. 尽量不在条件表达式中使用!取反
  24. 对于多常量选择分支,尽量使用switch语句而不是if-else语句
  25. 尽量不要使用正则表达式匹配
  26. 不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组
  27. 集合转化为类型T数组时,尽量传入空数组T[0]
  28. 不要使用循环拷贝集合,尽量使用JDK提供的方法拷贝集合
  29. 尽量重复使用同一缓冲区
  30. 尽量使用缓冲流减少IO操作
  31. 在单线程中,尽量使用非线程安全类
  32. 在多线程中,尽量使用线程安全类
  33. 尽量减少同步代码块范围
  34. 尽量使用线程池减少线程开销
    让代码更优雅
  35. 长整型常量后添加大写 L
  36. 不要使用魔法值
  37. 不要使用集合实现来赋值静态成员变量
  38. 建议使用 try-with-resources 语句
  39. 删除未使用的方法、参数、变量
  40. 公有静态常量应该通过类访问
  41. 使用String.valueOf(value)代替""+value
  42. 过时代码添加 @Deprecated 注解
  43. 尽量避免在循环中捕获异常
    让代码远离 bug
  44. 禁止使用构造方法 BigDecimal(double)
  45. 返回空数组和空集合而不是 null
  46. 优先使用常量或确定值来调用 equals 方法
  47. 枚举的属性字段必须是私有不可变
  48. 小心String.split(String regex)
    让代码性能更高
  49. 需要 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)。

  1. 不要把集合对象传给自己
    反例:

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
让代码更优雅

  1. 长整型常量后添加大写 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
  1. 尽量避免在循环中捕获异常
    反例:

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

  1. 禁止使用构造方法 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值