Java 我应该在 if-else 块中抛出异常吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/53941088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I throw exceptions in an if-else block?
提问by Lauda Wang
Here is the code:
这是代码:
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;
}
This program is working fine. I think it should be redesigned, but how?
这个程序运行良好。我认为它应该重新设计,但如何重新设计?
采纳答案by Eran
It makes no sense to throw an exception in a try block and immediately catch it, unless the catch block throws a different exception.
在 try 块中抛出异常并立即捕获它是没有意义的,除非 catch 块抛出一个不同的异常。
Your code would make more sense this way:
这样你的代码会更有意义:
public Response getABC(Request request) {
Response res = new Response();
if (request.someProperty == 1) {
// business logic
} else {
res.setMessage("xxxx");
}
return res;
}
You only need the try-catch block if your business logic (executed when the condition is true
) may throw exceptions.
如果您的业务逻辑(在条件为 时执行true
)可能抛出异常,则您只需要 try-catch 块。
If you don't catch the exception (which means the caller will have to handle it), you can do without the else
clause:
如果您没有捕获异常(这意味着调用者将不得不处理它),您可以不使用该else
子句:
public Response getABC(Request request) throws Exception {
if (request.someProperty != 1) {
throw new Exception("xxxx");
}
Response res = new Response();
// business logic
return res;
}
回答by mkjh
if you are throwing the exception from the method then why bother catching it ? it's either you return a response with "xxxx" message or throw an exception for the caller of this method to handle it.
如果您从方法中抛出异常,那为什么还要去捕捉它呢?您要么返回带有“xxxx”消息的响应,要么为此方法的调用者抛出异常来处理它。
public Response getABC(Request requst) {
Response res = new Response();
if(request.someProperty == 1){
//business logic
else{
res.setMessage("xxxx");
}
}
return res;
}
OR
或者
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;
}
}
回答by Dakshinamurthy Karra
First and foremost, tread more carefully when you refactor a working method - especially if you are performing a manual refactoring. That said, introducing a variable to hold message
may be one way of changing the design:
首先,在重构工作方法时要更加小心——尤其是在执行手动重构时。也就是说,引入一个变量来保持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;
}
The assumption is that the business logic
does it's own return when it succeeds.
假设是business logic
当它成功时它自己的回报。
回答by m fauzan abdi
it doesn't seems right when purposely throwing exception and then directly catch it,
it can be redesign like this,
can change throw new Exception("xxxx");
with res.setMessage("xxxx");
,
and then can keep the catching exception part in order to catch exception that may happen inside the business logic.
它似乎并不正确时,故意抛出异常,然后直接抓住它,它可以重新设计这样,
可以改变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;
}
回答by nhp
Why did you use try/catch statement when you already throw Checked Exception?
当您已经抛出Checked Exception时,为什么要使用 try/catch 语句?
Checked exceptionis usually used in some languages like C++ or Java, but not in new language like Kotlin. I personally restrict to use it.
检查异常通常用于某些语言,如 C++ 或 Java,但不适用于 Kotlin 等新语言。我个人限制使用它。
For example, I have a class like this:
例如,我有一个这样的类:
class ApiService{
Response getSomething() throw Exception();
}
which feels clean and readable, but undermines the utility of the exception handling mechanism. Practically, getSomething()
doesn't offen throw checked exception but still need to behave as it does? This works when there is somebody upstream of ApiService who know how to deal with the unpredictableor unpreventableerrors like this. And if you can really know how to deal with it, then go ahead and use something like the example below, otherwise, Unchecked Exceptionwould be sufficient.
这感觉干净和可读,但破坏了异常处理机制的效用。实际上,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")
}
}
I will encourage to do in this way:
我会鼓励这样做:
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
}
}
For more insights, Kotlin
which I mentioned before doesn't support Checked exceptionbecause of many reasons.
有关更多见解,Kotlin
我之前提到的由于多种原因不支持Checked 异常。
The following is an example interface of the JDK
implemented by StringBuilder
class:
以下是JDK
由StringBuilder
类实现的示例接口:
Appendable append(CharSequence csq) throws IOException;
What does this signature say? It says that every time I append a string to something (a StringBuilder
, some kind of a log, a console, etc.) I have to catch those IOExceptions
. Why? Because it might be performing IO
(Writer also implements Appendable
)… So it results into this kind of code all over the place:
这个签名是什么意思?它说每次我将一个字符串附加到某些东西(a StringBuilder
,某种日志,控制台等)时,我都必须捕获那些IOExceptions
. 为什么?因为它可能正在执行IO
(Writer 也实现了Appendable
)......所以它会导致到处都是这种代码:
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}
And this is no good, see Effective Java, 3rd Edition, Item 77: Don't ignore exceptions.
这不好,请参阅Effective Java,第 3 版,第 77 条:不要忽略异常。
Take a look at these links:
看看这些链接:
- Checked and unchecked exception
- Java's checked exceptions were a mistake(Rod Waldhoff)
- The Trouble with Checked Exceptions(Anders Hejlsberg)
- 检查和未检查异常
- Java 的检查异常是一个错误(Rod Waldhoff)
- 检查异常的问题(Anders Hejlsberg)
回答by Thorbj?rn Ravn Andersen
The exception mechanism has three purposes:
异常机制有三个目的:
- Immediately disable normal program flow and go back up the call stack until a suitable catch-block is found.
- Provide context in form of the exception type, message and optionally additional fields that the catch-block code can use to determine course of action.
- A stack trace for programmers to see to do forensic analysis. (This used to be very expensive to make).
- 立即禁用正常程序流并返回调用堆栈,直到找到合适的 catch 块。
- 以异常类型、消息和可选的附加字段的形式提供上下文,catch-block 代码可以使用这些字段来确定操作过程。
- 供程序员查看以进行取证分析的堆栈跟踪。(这曾经是非常昂贵的制作)。
This is a lot of functionality for a mechanism to have. In order to keep programs as simple as we can - for future maintainers - we should therefore only use this mechanism if we reallyhave to.
对于一个机制来说,这是很多功能。为了让程序尽可能简单——对于未来的维护者——我们应该只在确实需要时才使用这种机制。
In your example code I would expect any throw
statement to be a very serious thing indicating that something is wrong and code is expected to handle this emergency somewhere. I would need to understand what went wrong and how severe it is before going on reading the rest of the program. Here it is just a fancy return of a String, and I would scratch my head and wonder "Why was this necessary?" and that extra effort could have been better spent.
在您的示例代码中,我希望任何throw
语句都是非常严重的事情,表明出现问题并且代码应该在某处处理这种紧急情况。在继续阅读程序的其余部分之前,我需要了解出了什么问题以及问题的严重程度。这里只是一个字符串的花哨返回,我会挠头想知道“为什么这是必要的?” 并且本可以更好地花费额外的努力。
So this code is not as good as it can be, but I would only change it if you had the time to do a full test too. Changing program flow can introduce subtle errors and you need to have the changes fresh in your mind if you need to fix anything.
所以这段代码并不像它所能达到的那么好,但如果你也有时间做一个完整的测试,我才会改变它。更改程序流程可能会引入细微的错误,如果您需要修复任何内容,您需要牢记这些更改。
回答by Bill K
I think you might be missing the point of that try/catch. The code is using the exception system to bubble any exception message to the caller. This could be deep inside a nested call stack--not just the one "throws" you are looking at.
我认为您可能错过了 try/catch 的重点。该代码使用异常系统将任何异常消息冒泡给调用者。这可能位于嵌套调用堆栈的深处——而不仅仅是您正在查看的“抛出”堆栈。
In other words, the "throws" declaration in your example code is taking advantage of this mechanism to deliver a message to the client, but it almost certainly isn't the primary intended user of the try/catch. (Also it's a sloppy, kinda cheap way to deliver this message--it can lead to confusion)
换句话说,示例代码中的“throws”声明正在利用这种机制向客户端传递消息,但它几乎肯定不是 try/catch 的主要预期用户。(而且,这是一种草率、廉价的传递此信息的方式——它可能会导致混淆)
This return value isn't a great idea anyway because Exceptions often don't have messages and can be re-wrapped... it's better than nothing though. Exception messages just aren't the best tool for this, but handling an exception at a high level like this is still a good idea.
无论如何,这个返回值并不是一个好主意,因为异常通常没有消息并且可以重新包装……不过总比没有好。异常消息并不是最好的工具,但是像这样在高级别处理异常仍然是一个好主意。
My point is, if you refactor this code be sure to look for runtime exceptions that might be thrown anywhere in your code base (at least anywhere called during message processing)--and even then you should probably keep the catch/return message as a catch-all just in case a runtime exception pops up that you didn't expect. You don't have to return the error "Message" as the message of your response--It could be some quippy "We couldn't process your request at this time" instead, but be sure to dump the stack trace to a log. You are currently throwing it away.
我的观点是,如果您重构此代码,请务必查找可能在您的代码库中的任何地方(至少在消息处理期间调用的任何地方)抛出的运行时异常——即使如此,您也应该将捕获/返回消息保留为万一出现您没想到的运行时异常。您不必将错误“消息”作为您的响应消息返回——它可能是一些俏皮的“我们此时无法处理您的请求”,但请务必将堆栈跟踪转储到日志中. 你目前正在扔掉它。
回答by Deepak Bhavale
Same if you want to get the specific exception message returned by JVM on failure, that time you can use the try-catch with methods getMessage() or printStackTrace() in the catch block. So here you can modify your code like :
如果您想在失败时获取 JVM 返回的特定异常消息,那么您可以使用 try-catch 和 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;
}