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

Lau*_*ang 29 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;
}
Run Code Online (Sandbox Code Playgroud)

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

Era*_*ran 44

除非catch块抛出不同的异常,否则在try块中抛出异常并立即捕获它是没有意义的.

你的代码会更有意义:

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

如果业务逻辑(在条件执行时执行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;
}
Run Code Online (Sandbox Code Playgroud)


mkj*_*kjh 16

如果你从方法中抛出异常那么为什么还要去抓它呢?它要么返回带有"xxxx"消息的响应,要么为此方法的调用者抛出异常来处理它.

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

要么

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


public void someMethod(Request request) {
    try {
        Response r = getABC(request);
    } catch (Exception e) {
        //LOG exception or return response with error message
        Response response = new Response();
        response.setMessage("xxxx");
        retunr response;
    }

}
Run Code Online (Sandbox Code Playgroud)


m f*_*bdi 9

它似乎并不正确时,故意抛出异常,然后直接抓住它,它可以重新设计这样,
可以改变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;
}
Run Code Online (Sandbox Code Playgroud)


Dak*_*rra 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;
}
Run Code Online (Sandbox Code Playgroud)

假设是business logic成功后它自己返回.


Bil*_*l K 7

我想你可能会忽略try/catch的重点.代码使用异常系统将任何异常消息冒泡到调用者.这可能是嵌套调用堆栈内部的深层 - 而不仅仅是您正在查看的那个"抛出".

换句话说,示例代码中的"throws"声明正在利用此机制向客户端传递消息,但它几乎肯定不是try/catch的主要预期用户.(这也是一种草率,有点廉价的方式来传递这个信息 - 它可能导致混乱)

无论如何,这个返回值并不是一个好主意,因为Exceptions通常没有消息并且可以重新包装......但它总比没有好.异常消息不是最好的工具,但是在这样的高级别处理异常仍然是一个好主意.

我的观点是,如果您重构此代码,请务必查找可能在代码库中的任何位置抛出的运行时异常(至少在消息处理期间调用的任何位置) - 即使这样,您应该将catch/return消息保留为catch-all以防万一弹出你没想到的运行时异常.您不必将错误"消息"作为响应的消息返回 - 它可能是一些quippy"我们此时无法处理您的请求",但请务必将堆栈跟踪转储到日志中.你现在正在抛弃它.


nhp*_*nhp 5

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

被检查的异常通常用于某些语言,如C++或Java,但不能用于像Kotlin这样的新语言.我个人限制使用它.

例如,我有一个这样的类:

class ApiService{
    Response getSomething() throw Exception(); 
} 
Run Code Online (Sandbox Code Playgroud)

感觉干净和可读,但破坏了异常处理机制的实用性.实际上,getSomething()不会抛出检查异常,但仍需要像它一样行事吗?当ApiService上游有人知道如何处理像这样的不可预测不可预防的错误时,这就有效.如果你真的知道如何处理它,那么继续使用类似下面的例子,否则,Unchecked Exception就足够了.

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

我会鼓励这样做:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

对于更多的见解,Kotlin我之前提到的由于许多原因不支持Checked异常.

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

Appendable append(CharSequence csq) throws IOException;
Run Code Online (Sandbox Code Playgroud)

这个签名是什么意思?它说每次我将一个字符串附加到某个东西(a StringBuilder,某种日志,控制台等)时,我必须抓住它们IOExceptions.为什么?因为它可能正在执行IO(Writer也实现Appendable)......所以它会产生这种代码到处:

try {
    log.append(message)
}
catch (IOException e) {
    // Must be safe
}
Run Code Online (Sandbox Code Playgroud)

这并不好,参见Effective Java,3rd Edition,Item 77:不要忽略异常.

看看这些链接: