《Effective Java》学习笔记--第3部分 方法设计和实现最佳实践

文章目录

    • 第3部分 方法设计和实现
      • 一、前言
      • 二、方法设计和实现最佳实践
        • 1. 方法的参数要尽量少
        • 2. 避免使用过多的返回值
        • 3. 避免在方法中返回 null
        • 4. 方法要尽量做到单一职责
        • 5. 使用合适的访问修饰符
        • 6. 避免方法内部的过多的条件分支
        • 7. 使用适当的异常处理
        • 8. 考虑方法的线程安全性
      • 三、小结


《Effective Java》学习笔记--第3部分 方法设计和实现最佳实践_第1张图片

第3部分 方法设计和实现

一、前言

《Effective Java》共有多个章节,每个章节提供了若干条建议或最佳实践,整理了对应章节关键的实践内容,用于自己后续代码开发过程中,参考对照,自查代码习惯,从而提升输出的代码质量。

当前我的编码要求是方法做到单一职责,每个方法的实现行数不要超过50行。这种方式可以避免裹脚布似的长代码,给自己和后来者留条活路。

二、方法设计和实现最佳实践

1. 方法的参数要尽量少
  • 原因:方法的参数数量越多,方法的复杂度和调用的难度就越高。多参数的方法不仅使得方法调用变得复杂,而且使得理解方法的意图变得困难。

  • 最佳实践:

    • 尽量使方法的参数数量保持在 3 个以内。如果超过了 3 个参数,考虑是否可以使用 对象封装参数,将多个参数包装成一个对象来传递。
    • 使用可变参数(varargs)时,要注意顺序,并且不应过多使用。
  • 示例:

    // 多参数的方法
    public void createUser(String name, String email, String phone, String address) {
        // 做一些事情
    }
    
    // 使用对象封装参数
    public void createUser(UserInfo userInfo) {
        // 做一些事情
    }
    
2. 避免使用过多的返回值
  • 原因:返回值过多可能导致方法的行为不明确,也可能导致方法的功能过于复杂。

  • 最佳实践:

    • 通过包装类或容器类来封装多个返回值,保持方法返回的简洁性。
    • 使用 Optional 来表示可能没有值的返回类型,避免返回 null
  • 示例:

    // 使用包装类封装多个返回值
    public class Result {
        private boolean success;
        private String message;
    
        public Result(boolean success, String message) {
            this.success = success;
            this.message = message;
        }
    
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
    }
    
    public Result doSomething() {
        return new Result(true, "Operation successful");
    }
    
3. 避免在方法中返回 null
  • 原因:返回 null 会增加调用方的错误处理负担,并且可能导致 NullPointerException。如果方法的返回值为 null,调用者需要额外的检查,增加了代码的复杂性。

  • 最佳实践:

    • 尽量避免返回 null,而是考虑返回一个空对象或一个空集合,甚至使用 Optional
  • 示例:

    // 不推荐返回 null
    public List<String> getItems() {
        return null;
    }
    
    // 推荐返回空集合
    public List<String> getItems() {
        return Collections.emptyList();
    }
    
    // 使用 Optional
    public Optional<String> getItem() {
        return Optional.ofNullable(item);
    }
    
4. 方法要尽量做到单一职责
  • 原因:方法的职责越单一,它就越容易理解和测试。避免让一个方法做太多的事情。

  • 最佳实践:

    • 确保每个方法都只做一件事情,并且该事情有清晰的目的。
    • 如果一个方法做的事情太多,考虑将它拆分成多个方法,每个方法负责一个小的功能。
  • 示例:

    // 不推荐:方法做了多件事
    public void processOrder(Order order) {
        validateOrder(order);
        calculateTotal(order);
        sendConfirmationEmail(order);
    }
    
    // 推荐:每个方法做一件事
    public void validateOrder(Order order) {
        // 校验订单
    }
    
    public void calculateTotal(Order order) {
        // 计算总价
    }
    
    public void sendConfirmationEmail(Order order) {
        // 发送确认邮件
    }
    
5. 使用合适的访问修饰符
  • 原因:方法的访问权限应当是最小的,这有助于控制对方法的访问,避免外部不必要的依赖。

  • 最佳实践:

    • 尽量将方法的访问修饰符设置为 privateprotected,只有当外部需要调用该方法时,才将其设置为 public
    • 尽量避免暴露不必要的 API,尤其是内部实现的辅助方法。
  • 示例:

    // 不推荐:不必要的公共方法
    public void helperMethod() {
        // 做一些辅助操作
    }
    
    // 推荐:设置为 private
    private void helperMethod() {
        // 做一些辅助操作
    }
    
6. 避免方法内部的过多的条件分支
  • 原因:大量的条件分支(如 if-elseswitch)会使得方法的逻辑变得复杂,难以理解和维护。

  • 最佳实践:

    • 尽量避免方法内部有过多的条件判断,可以使用 策略模式责任链模式 等设计模式来消除复杂的条件分支。
  • 示例:

    // 不推荐:大量的 if-else
    public String getUserType(User user) {
        if (user.isAdmin()) {
            return "Admin";
        } else if (user.isGuest()) {
            return "Guest";
        } else {
            return "User";
        }
    }
    
    // 推荐:使用策略模式
    public String getUserType(User user) {
        UserTypeStrategy strategy = getUserTypeStrategy(user);
        return strategy.getType(user);
    }
    
7. 使用适当的异常处理
  • 原因:异常应该用于表示程序中的错误情况,而不是用来控制流程。异常的使用应该合理,避免不必要的抛出和捕获。

  • 最佳实践:

    • 在方法中不要滥用异常,应该在出现真正的错误时才抛出异常。
    • 使用具体的异常类型而非通用的 Exception 类。
    • 捕获异常时,最好给出明确的错误信息,以便后续调试。
  • 示例:

    // 不推荐:捕获所有异常
    try {
        // 做一些事情
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    // 推荐:捕获特定异常
    try {
        // 做一些事情
    } catch (IOException e) {
        // 处理文件IO异常
    } catch (SQLException e) {
        // 处理数据库异常
    }
    
8. 考虑方法的线程安全性
  • 原因:在多线程环境中,如果方法访问共享资源或修改对象的状态,必须考虑方法的线程安全性。

  • 最佳实践:

    • 使用 synchronized 关键字,或者更高效的 java.util.concurrent 包中的工具来确保线程安全。
  • 示例:

    // 使用 synchronized 保证线程安全
    public synchronized void increment() {
        counter++;
    }
    

三、小结

《Effective Java》第3部分“方法”讲解了方法设计的多个关键最佳实践,包括如何处理参数、返回值、异常、线程安全等。合理设计方法可以极大提高代码的可维护性和可读性,同时避免常见的编程错误。开发时应尽量遵循这些设计准则,以编写更加清晰、简洁、高效的代码。

你可能感兴趣的:(Effective,Java最佳实践笔记,java,学习,笔记)