例如,我有一个方法

void process(String userId) {
  if(userId == null) throw new IlligalArgumentException("Usesr ID is required);

  User user = userService.findUserById(userId);

  if(user == null) throw new UserNotFoundException("User with ID: "+ userId +" not found");
  
  try {
     DataResponse response = analyticsAPI.loadAnalytics(userId, user.getDob(), user.getFirstName());  

     //logic
   } catch(AnalyticsAPIException e) {
     //logic
   }
 }
  1. IlligalArgumentExceptionunchecked例外
  2. UserNotFoundExceptionunchecked例外
  3. AnalyticsAPIExceptionchecked例外

我读到,最好的做法是从try开始,然后用catch结束,而不是在one方法中乘以try-catch块.

我们更喜欢例外而不是错误代码

比如:

void process(String userId) {
  try {
      if(userId == null) throw new IlligalArgumentException("Usesr ID is required);
    
      User user = userService.findUserById(userId);
    
      if(user == null) throw new UserNotFoundException("User with ID: "+ userId +" not found");
      
         DataResponse response = analyticsAPI.loadAnalytics(userId, user.getDob(), user.getFirstName());  

         //logic
       } catch(AnalyticsAPIException e) {
         //logic
       }
     }

但看起来很奇怪.我在try-catch块中抛出了一个异常,希望它不会在catch中被处理.我希望它将被抛出到调用该方法的服务的上面.

下一步我可以做:

public void process(String userId) {
          try {
              if(userId == null) throw new IlligalArgumentException("Usesr ID is required);
            
              User user = userService.findUserById(userId);
            
              if(user == null) throw new UserNotFoundException("User with ID: "+ userId +" not found");
              
              DataResponse response = callApi(userId, user.getDob(), user.getFirstName());  
        
              //logic
             }
    
private DataResponse callApi(String userId, Date dob, String firstName){
               try {
                 return analyticsAPI.loadAnalytics(userId, user.getDob(), user.getFirstName());  
               } catch(AnalyticsAPIException e) {
                 //logic
               }
         }

但它并不总是有效.那么,什么更好呢?

推荐答案

Bob建议的是,在try或catch块中没有语句列表.相反,你应该将"正常"情况与例外情况分开.目标是分离不同的抽象层次.

为了避免名字冲突,我经常在"normal"前加上"try"这个词.

"处理"方法应该关注"处理用户(userId)"的含义.这是一个抽象层次,如果你把它与其他方法分开,它更容易阅读和理解.

void process(String userId) {
    User user = getUserById(userId);

    loadAnalytics(user);
}

getUserById只关注当您想通过用户id获取用户时所需的逻辑.

void void getUserById(String userId){
    if(userId == null) throw new IlligalArgumentException("Usesr ID is required");
    
    User user = userService.findUserById(userId);
    if(user == null) throw new UserNotFoundException("User with ID: "+ userId +" not found");
    
    return user;
}

要理解"过程"方法,不需要理解

但是当你深入研究loadAnalytics方法时,你想知道它是如何工作的.现在,您可以立即看到加载分析可能会导致异常状态.该方法主要关注异常处理,因为它只包含try/catch,而且还关注可能发生的异常类型.

void loadAnalytics(User user){
    try {
     tryLoadAnalytics(user);
    } catch(AnalyticsAPIException e) {
     handleAnalyticsError(e);
    }
}

我经常使用"try"前缀来避免名称冲突,并明确说明方法可能会失败.

void tryLoadAnalytics(){
    DataResponse response = callApi(userId, user.getDob(), user.getFirstName());  
    
    //logic
}

与"正常"情况一样,异常处理是分开的,这样您就可以关注如何处理特定的异常.

void handleAnalyticsError(AnalyticsAPIException e){
    //logic
}

Java相关问答推荐

Spring boot:Bean和动态扩展器

为什么Java的代码工作(if condition内部的实例)

根据对象和值的参数将映射<;T、值&>转换为列表<;T&>

Java FX中的河内之塔游戏-在游戏完全解决之前什么都不会显示

在运行MVN测试时,为什么构建失败,并显示了java.lang.ClassNotFoundException:java.net.http.HttpResponse?

通过移动一个类解决了潜在的StubbingProblem.它怎麽工作?

将响应转换为带值的键

如何集成语义发布和BitBucket(Java项目)

解析方法";javax/imageio/metadata/IIOMetadata.getAsTree(Ljava/lang/String;)Lorg/w3c/dom/Node时加载约束冲突

在处理2个映射表时,没有更多的数据可从套接字读取

为什么有两种实现来检索数组类的组件类型?

AWS Java SDK v2.x中没有setObjectAcl方法

如何利用OpenTelemeter将初始值(零)输出到普罗米修斯

无限递归Java问题

Java递归泛型是否可以被视为继承和重写的语法糖

整数->;双取消框,但双->;int不';t开箱.为什么?

如何使用带有可选参数的类生成器?

如何使用java区分以下结果

Spring Boot应用程序中的自定义constraintvalidator不会被调用

在数组列表中找到对象后,未从数组中删除对象