重新抛出已检查的异常
public void foo() {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
throw e;
}
}
在上面的示例中,出现错误是因为 foo
没有 throws Exception
。添加这一点也不会使该方法的可用性变得很好。
最好的方法是什么?如果发生错误而没有真正“处理”错误,您该如何处理?
public void foo() {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
throw e;
}
}
In the sample above, there is an error because foo
has no throws Exception
. Adding that wouldn't make do the method's usability a lot of good either.
What's the best way to do this? How do you do something if an error occurs without really "handling" the error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
从 Java 8 开始,
我们可以重新抛出检查异常,但只能通过避免编译器检查异常验证。
在使用 stop() 之前,您应该阅读 http:// download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Since Java 8 we use
You can rethrow a checked exception, but only by avoiding the compilers checked exception validation.
Before you use stop() you should read http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
我至少会想到两种方法,通常会组合,具体取决于您希望
foo
执行的操作:1. 仅捕获并重新抛出相关异常
只有主流程中的代码可能会抛出如此多的异常(可能主要是
SqlException
)。因此,只能捕获并重新抛出它们,并声明您正在这样做。更重要的是,仅重新抛出那些您实际上没有处理的代码(在简化的示例代码中,您没有处理任何代码,但您的现实生活代码可能更微妙)。请注意,某些异常可能是运行时异常,因此您可能希望将其与以下异常结合起来。
2.根本不要捕获异常
像这样:
当然,您的签名需要包含主流中可能引发的任何异常,但这就是您想要做的,如果我理解正确的话。
同样,您很可能结合这两种方法,因为您可能想要处理一些异常而不是其他异常。
At least two approaches come to mind, which are usually going to be combined depending on what you want
foo
to do:1. Catch and rethrow only the relevant exceptions
There are only so many exceptions the code in your main flow can throw (probably mostly
SqlException
s). So only catch and rethrow those, and declare that you're doing so. More to the point, rethrow only the ones you're not actually handling (in your simplified sample code, you're not handling any, but your real life code is probably more subtle).Mind you, some of the exceptions may be runtime exceptions, and so you may want to combine this with the below.
2. Don't catch the exception at all
Like this:
Naturally your signature needs to include any exceptions that may be thrown in the main flow, but that's what you're trying to do, if I'm understanding you correctly.
Again, you may well combine these two approaches, because you may want to handle some exceptions and not others.
用一些未检查的 RuntimeException 包裹它。
Wrap it with some RuntimeException which is unchecked.
不。它将擅长记录文档,并且调用者也会小心处理它。
另请参阅
异常抛出-inside-catch-block-will-it-be-caught-again
抛出-or-try-catch
No. It will be good at documentation, also caller will take care handling it.
Also See
exception-thrown-inside-catch-block-will-it-be-caught-again
throws-or-try-catch
我想说,在这种情况下回滚就是适当地处理异常。这是少数可以合法接球并重新投掷的情况之一。
我不会考虑处理简单地捕获和记录异常。在这种情况下,我宁愿看到已检查的异常添加到方法签名中并让它冒泡,而不是重新抛出。
I'd say that in this case rolling back is handling the exception appropriately. It's one of the few cases where it's legitimate to catch and re-throw.
Simply catching and logging an exception is not what I would consider handling. Rather than rethrowing, in that case I'd rather see checked exceptions added to the method signature and let it bubble up.
你可以抛出 RuntimeException 的子类 - 它们不需要 catch()
you may throw a subclass of RuntimeException - they don't require a catch()
关键点是,为什么要从 catch 块中抛出新的异常。
如果你使用catch,那么在你的catch中处理你的异常。如果您必须向调用方方法通知异常,那么不要使用 try-catch 捕获异常,而是使用 throws 标记您的方法并让调用方捕获异常。
或者抛出一个 RuntimeException,我发现这个想法不太有用,因为缺乏可读性,那么你不需要用 throws 来签署你的方法。
the key point is, why should you throw a new Exception from a catch block.
if you use catch then handle your exception there in your catch. If you have to inform the caller method with an exception, then don't catch the exception with try-catch, instead, sign your method with throws and let the caller catch the e xception.
or throw a RuntimeException, i find this idea less useful because of lack of readability, then you don't need to sign your method with throws.
在这里,您遇到了爪哇(如果不是更广泛的)世界上最大的宗教分裂之一。归根结底,那些感觉检查异常很有价值的人(TJ 似乎也这么觉得,我也这么认为)有很多原因,而 Rod Johnson/Spring 学派认为,在 Java 的设计中,检查异常在许多情况下都被使用不应该,比如关闭结果集或套接字,所以因为它在很多情况下被错误地使用,这使得它们变得无用,所以所有异常都应该被取消检查。 Spring 框架中有许多类是标准 Java 对象的非常薄的包装器,但将检查异常转换为未检查异常。它让我发疯!
不管怎样,我强烈同意 TJ 所说的一切,但要知道你可能永远找不到“正确”的答案。
Here you've chanced on one of the biggest religious schisms in the Java, ( if not wider ) , world. It boils down to those that feel, as TJ seems to, and I do too, that checked exceptions are valuable for many reasons, VS the Rod Johnson/Spring school that in the design of Java, checked exceptions were used in many instances where they shouldn't, say closing a resultset or socket, so because it was wrongly used in many cases, it makes them useless so all exceptions should be unchecked. There are many classes in the Spring framework that are very thin wrappers around standard Java objects, but convert checked exceptions to unchecked. It drives me berserk!
Anyway, put me down as strongly agreeing with everything TJ has said, but know that you'll probably never find a "right" answer.
值得一提的是该领域的一些进展。
首先,在 Java 7 中,只要在 try 块内声明的内容在外部块中捕获或声明,就可以捕获并抛出通用异常。所以这将编译:
这里有很好的解释: http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
这里描述了另一种方法:http://blog.jooq.org/2012/09/14/throw-checked -exceptions-like-runtime-exceptions-in-java/
您可能想要使用它的原因通常与 lambda 或从某些通用方法抛出异常有关。当我想替换以下重复结构时,我遇到了这个问题:
使用以下方法:
因此将整个 try/catch 块替换为
It's worth mentioning some advances in this area.
First, in Java 7, it's possible to catch and throw generic exceptions, as long as what's declared inside the try block is caught or declared in the outer block. So this would compile:
This is well explained here : http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Another way is described here : http://blog.jooq.org/2012/09/14/throw-checked-exceptions-like-runtime-exceptions-in-java/
The reason you may want to use that has often to do with lambdas, or throwing exceptions from some generic methods. I ran into this when I wanted to replace repeating constructs of:
With using a method of:
and therefore replacing the whole try/catch block with just
如果您使用 Java 7 或更高版本,则可以声明该函数以抛出与
try
块中的代码相同的已检查异常。此更改在重新抛出部分中详细描述具有更具包容性的类型检查的异常。简而言之,您可以捕获从
try
块抛出的异常类型的超类型,然后重新抛出它,而无需任何额外的检查异常。因此,如果try
块中的代码仅引发运行时异常,您仍然可以捕获并重新抛出Exception
甚至Throwable
,而无需声明任何已检查异常。If you use Java 7 or newer, you can declare the function to throw the same checked exceptions as the code in the
try
block. This change is described in detail in the section Rethrowing Exceptions with More Inclusive Type Checking.In brief, you can catch a supertype of the exception types thrown from a
try
block and then rethrow it without any extra checked exceptions. So if the code in thetry
block only throws runtime exceptions, you can still catch and rethrowException
or evenThrowable
without declaring any checked exceptions.