我应该在if-else块中抛出异常吗?

时间:2018-12-27 07:08:00

标签: java if-statement exception throw

代码如下:

public Response getABC(Request request) throws Exception {
    Response res = new Response();
    try {
        if (request.someProperty == 1) {
            // business logic
        } else {
           throw new Exception("xxxx");
        }
    } catch (Exception e) {
        res.setMessage(e.getMessage); // I think this is weird
    }
    return res;
}

该程序运行正常。 我认为应该重新设计它,但是如何?

8 个答案:

答案 0 :(得分:43)

除非在catch块中引发了其他异常,否则在try块中引发异常并立即对其进行捕获是没有意义的。

您的代码通过这种方式更有意义:

public Response getABC(Request request) {
    Response res = new Response();
    if (request.someProperty == 1) {
        // business logic
    } else {
        res.setMessage("xxxx");
    }
    return res;
}

仅当您的业务逻辑(在条件为true时执行)可能引发异常时,才需要try-catch块。

如果没有捕获到异常(这意味着调用者必须处理该异常),则可以不使用else子句:

public Response getABC(Request request) throws Exception {
    if (request.someProperty != 1) {
        throw new Exception("xxxx");
    }

    Response res = new Response();
    // business logic
    return res;
}

答案 1 :(得分:15)

如果您从方法中抛出异常,那为什么还要麻烦捕获它呢?它要么返回带有“ xxxx”消息的响应,要么抛出异常,以供此方法的调用者处理。

"styles": [
          "../node_modules/bootstrap/dist/css/bootstrap.min.css",
          "../src/styles.css"

        ],

OR

public Response getABC(Request requst) {
    Response res = new Response();
        if(request.someProperty == 1){
            //business logic
        else{
           res.setMessage("xxxx");
        }
    }
    return res;
}

答案 2 :(得分:8)

故意抛出异常然后直接捕获它似乎并不正确, 可以这样重新设计,
可以用throw new Exception("xxxx");更改res.setMessage("xxxx");
然后可以保留捕获异常部分,以捕获业务逻辑内部可能发生的异常。

public Response getABC(Request requst) {
  Response res = new Response();
  try{
      if(request.someProperty == 1){
          //business logic
      else{
         res.setMessage("xxxx");
      }
  }catch(Exception e){
      res.setMessage(e.getMessage);
  }
  return res;
}

答案 3 :(得分:7)

首先,在重构工作方法时应特别小心,尤其是在执行手动重构时。也就是说,引入变量来保存message可能是更改设计的一种方法:

public Response getABC(Request requst) throw Excetpions {
    String message = "";
    try{
        if(request.someProperty == 1){
            //business logic
        else{
           message = "xxxx";
        }
    }catch(Exception e){
        message = e.getMessage();
    }
    Response res = new Response();
    res.setMessage(message);
    return res;
}

假设business logic成功时是自己返回。

答案 4 :(得分:7)

我认为您可能会错过尝试/捕获的要点。该代码使用异常系统将任何异常消息冒泡给调用者。这可能位于嵌套调用堆栈的深处,而不仅仅是您正在查看的那个“抛出”。

换句话说,示例代码中的“ throws”声明正在利用此机制将消息传递给客户端,但是几乎可以肯定,它不是try / catch的主要目标用户。 (这也是一种草率,便宜的方式来传达此信息-可能会导致混乱)

无论如何,此返回值并不是一个好主意,因为异常通常没有消息,并且可以重新包装……总比没有好。异常消息并不是解决此问题的最佳工具,但是像这样从高层次处理异常仍然是个好主意。

我的意思是,如果您重构此代码,请确保查找可能在代码库中的任何地方抛出的运行时异常(至少在消息处理期间调用的任何地方),并且即使这样,您也可能应保持捕获/返回消息作为一个包罗万象,以防万一弹出意外的运行时异常。您不必将错误“ Message”作为响应的消息返回-可能有点“我们现在无法处理您的请求”,但请确保将堆栈跟踪信息转储到日志中。您目前正在扔掉它。

答案 5 :(得分:5)

为什么您已经抛出 Checked Exception 时为什么使用try / catch语句?

受检查的异常通常用于某些语言(例如C ++或Java),而不用于新语言(例如Kotlin)。我个人限制使用它。

例如,我有一个这样的课程:

class ApiService{
    Response getSomething() throw Exception(); 
} 

看上去很干净而且可读,但是破坏了异常处理机制的实用性。实际上,getSomething()不会冒犯已检查的异常,但仍然需要像它一样行为吗?当ApiService上游有人知道如何处理这样的不可预测不可预防错误时,此方法有效。并且,如果您真的知道如何处理它,请继续使用下面的示例,否则,未检查的异常就足够了。

public Response getSomething(Request req) throws Exception{
    if (req.someProperty == 1) {
        Response res = new Response();
        // logic 
    } else {
        thows Exception("Some messages go here")
    }
}

我鼓励这样做:

public Response getSomething(Request req){
if (req.someProperty == 1) {
        Response res = new Response();
        // logic 
        return res;
    } else {
        return ErrorResponse("error message"); // or throw RuntimeException here if you want to
    }
}

有关更多见解,由于多种原因,我之前提到的Kotlin不支持已检查异常

以下是JDK类实现的StringBuilder的示例接口:

Appendable append(CharSequence csq) throws IOException;

这个签名怎么说?它说每次我将字符串附加到某个内容(StringBuilder,某种日志,控制台等)时,都必须捕获那些IOExceptions。为什么?因为它可能正在执行IO(Writer还实现了Appendable)……所以它遍及整个地方都变成了这种代码:

try {
    log.append(message)
}
catch (IOException e) {
    // Must be safe
}

这不好,请参阅 Effective Java,第三版,条款77 :不要忽略异常。

看看这些链接:

答案 6 :(得分:3)

异常机制具有三个目的:

  1. 立即禁用正常的程序流程,并返回调用堆栈,直到找到合适的catch块为止。
  2. 以异常类型,消息以及可选的其他字段的形式提供上下文,捕获代码可用于确定操作过程。
  3. 堆栈跟踪信息,供程序员查看以进行取证分析。 (这过去制作起来非常昂贵)。

机制具有许多功能。为了使程序尽可能地简单(对于将来的维护者),因此,我们仅在确实需要时才使用此机制。

在您的示例代码中,我希望任何throw语句都是一件非常严肃的事情,表明有问题,并且代码有望在某些地方处理这种紧急情况。在继续阅读该程序的其余部分之前,我需要先了解问题所在和严重程度。在这里,这只是String的幻想返回,我会挠头,想知道“为什么需要这样做?”而且本来可以花更多的精力。

因此,这段代码虽然不尽如人意,但只有在您也有时间进行完整测试的情况下,我才会对其进行更改。更改程序流程可能会引入细微的错误,如果需要修复任何问题,则需要立即进行更改。

答案 7 :(得分:3)

与如果要获取JVM在失败时返回的特定异常消息相同,那时候您可以在catch块中将try-catch与方法getMessage()或printStackTrace()一起使用。因此,您可以在此处修改代码:

public Response getABC(Request request) throws Exception {
    Response res = new Response();
    try {
        if (request.someProperty == 1) {
            // business logic
        } 
    } catch (Exception e) {
        res.setMessage(e.getMessage); 
    }
    return res;
}