如何让你的java代码性能"更高、更优雅、远离BUG"?( 三 )

正例:
private static String readFile(String fileName) throws IOException { try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { String line; StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line); } return builder.toString(); }}2.11.公有静态常量应该通过类访问
虽然通过类的实例访问公有静态常量是允许的,但是容易让人它误认为每个类的实例都有一个公有静态常量 。所以,公有静态常量应该直接通过类访问 。
反例:
public class User { public static final String CONST_NAME = "name"; ...}User user = new User();String nameKey = user.CONST_NAME;正例:
public class User { public static final String CONST_NAME = "name"; ...}String nameKey = User.CONST_NAME;2.12.不要用 NullPointerException 判断空
空指针异常应该用代码规避(比如检测不为空),而不是用捕获异常的方式处理 。
反例:
public String getUserName(User user) { try { return user.getName(); } catch (NullPointerException e) { return null; }}正例:
public String getUserName(User user) { if (Objects.isNull(user)) { return null; } return user.getName();}2.13.使用 String.valueOf(value) 代替 ""+value
当要把其它对象或类型转化为字符串时,使用 String.valueOf(value) 比 ""+value 的效率更高 。
反例:
int i = 1;String s = "" + i;正例:
int i = 1;String s = String.valueOf(i);2.14.过时代码添加 @Deprecated 注解
当一段代码过时,但为了兼容又无法直接删除,不希望以后有人再使用它时,可以添加 @Deprecated 注解进行标记 。在文档注释中添加 @deprecated 来进行解释,并提供可替代方案
正例:
/** * 保存 * * @deprecated 此方法效率较低,请使用{@link newSave()}方法替换它 */@Deprecatedpublic void save(){ // do something}03 如何让代码远离 bug3.1.禁止使用构造方法 BigDecimal(double)
BigDecimal(double) 存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常 。
反例:
BigDecimal value = https://www.isolves.com/it/cxkf/yy/JAVA/2019-09-29/new BigDecimal(0.1D); // 0.100000000000000005551115...正例:
BigDecimal value = https://www.isolves.com/it/cxkf/yy/JAVA/2019-09-29/BigDecimal.valueOf(0.1D);; // 0.13.2.返回空数组和空集合而不是 null
返回 null,需要调用方强制检测 null,否则就会抛出空指针异常 。返回空数组或空集合,有效地避免了调用方因为未检测 null 而抛出空指针异常,还可以删除调用方检测 null 的语句使代码更简洁 。
反例:
public static Result[] getResults() { return null;}public static List<Result> 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) { ... } }}正例:
public static Result[] getResults() { return new Result[0];}public static List<Result> 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) { ... }}3.3.优先使用常量或确定值来调用 equals 方法
对象的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals 方法 。当然,使用java.util.Objects.equals() 方法是最佳实践 。
反例:
public void isFinished(OrderStatus status) { return status.equals(OrderStatus.FINISHED); // 可能抛空指针异常}正例:
public void isFinished(OrderStatus status) { return OrderStatus.FINISHED.equals(status);}public void isFinished(OrderStatus status) { return Objects.equals(status, OrderStatus.FINISHED);}3.4.枚举的属性字段必须是私有不可变
枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改 。理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的 Setter 方法,最好加上 final 修饰符 。
反例:
public enum UserStatus { DISABLED(0, "禁用"), ENABLED(1, "启用"); public int value; private String description; private UserStatus(int value, String description) { this.value = https://www.isolves.com/it/cxkf/yy/JAVA/2019-09-29/value; this.description = description; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; }}


推荐阅读