在 java 中,通过函数调用将运行时异常用作超级 "break" 是一种不好的做法吗?

In java, is it bad practice to use Runtime Exception as a super "break" through function calls?

有时,有一系列的函数调用,在中间你确定了结果,你想在中间停止整个函数链。在这种情况下,下面的方式不好吗?

public ResponseObject composeResponse {
   try {
       ResponseObject response = new ResponseObject();
       processA(response);
       processB(response);
       processC(response);
       processD(response);
          .
          .
          .
       return response;
       } catch (SomeFlagException e){
       return response;        
       }
   }

对于每个流程函数,它也像

public void processA(ResponseObject response){
    minorProcess1(response);
    minorProcess2(response);
    minorProcess3(response);
      .
      .
      .
}

在某些特定条件下,比如minorProcess3(),有这样的情况,即结果已确定,而其余的过程不需要。假设这发生在很多次要进程中。

public void minorProcess3(ResponseObject response){
    //some process
    if (someFlag){
        //want end the process and return the result
        throw new SomeFlagException(); //SomeFlagException extends RuntimeException
    }
}

我的想法告诉我不,因为这不是一个“例外”,而是一个意料之中的结果。而且听说unchecked Exception只有在无法合理解决的情况下才应该抛出。但我只能想出这样的方法来让代码干净,否则代码将不得不将条件检查一直级联回基函数。

编辑:添加有关我的情况的信息。这是一个 web 项目,因此它假设 return 对负载进行适当的响应。有时请求应由 204/40x 响应。不需要负载,因此不需要进一步处理,应该放弃。

是的,这样做是非常糟糕的做法。

异常意味着某些方法无法履行其合同。您询问的方法恰恰相反:使用异常意味着早日成功。

虽然它在技术上可行,但它与异常的预期含义背道而驰,我不得不强烈建议不要使用这种方法。

And I heard that unchecked Exception should only be throwed when it cannot be reasonably resolved.

恕我直言,这是个糟糕的建议。作为抛出异常的人,您如何知道调用堆栈上的某个调用方方法在您失败后是否可以继续成功?这只能在调用者的上下文中确定(它是否具有针对失败的回退策略),并且很少取决于异常的类型。决定那个不是你的责任,即使你试图做出那个决定,结果也很可能是错误的。

例如对于您的来电者,您是否因 NullPointerExceptionIOException 而失败通常无关紧要,仅举两个未检查/已检查类别的突出示例。重要的是,你失败了,也许来电者知道你失败后如何继续。

您应该抛出异常作为算法逻辑的一部分。异常必须表明某些我们不希望出错

一种更简洁的方法是让 process(ResponseObject)minorProcess(ResponseObject) 方法 return 一个 boolean 值指示响应过程是否应该继续。

参见示例:

public boolean processX(ResponseObject response)
{
    boolean shouldContinue;

    shouldContinue = shouldContinue && minorProcess1(response);
    shouldContinue = shouldContinue && minorProcess2(response);
    shouldContinue = shouldContinue && minorProcess3(response);
      .
      .
      .

   return shouldContinue;
}

使用 && 运算符时,如果第一个条件为假,则不计算第二个条件。

minorProcess 示例:

/**
*
*/
public boolean minorProcessX(ResponseObject response)
{
    //some process
    if (someFlag)
    {
        //want end the process and return the result
        return false;
    }
 }