>我有以下代码
try {
....
} catch (Exception e) {
log.error(String.format(SOME_CUSTOM_VARIABLE, e);
throw e;
}
我希望异常SOME_CUSTOM_STRING_WITH_VARIABLES获取字符串。
所以我想做的是
try {
....
} catch (Exception e) {
log.error(String.format(SOME_CUSTOM_VARIABLE, e);
throw new Exception(SOME_CUSTOM_VARIABLE, e);
}
但这迫使我在方法签名中添加"抛出异常"。
无论如何,此方法都会引发异常。为什么我必须更改签名?
如何将基本异常替换为另一个异常?
因为引发异常意味着创建自己的方法throws
Exception
,因此您需要声明该方法throws
它,以便该方法的用户知道catch
它。 就像你一开始就不得不在试抓中包围它一样。如果没有强制声明您的方法throws
那么Exception
可能会丢失。
如果您不想更改方法签名,则可以创建自定义RuntimeException
并抛出它。
但请注意后果:
- 如果在上层类中未正确捕获此自定义
RuntimeException
,则可能会使整个程序崩溃。 - 这更像是一种解决方法,当抛出
RuntimeException
时,程序不应从异常中恢复。运行时异常表示由编程问题引起的问题。
关于这方面的一些信息: https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
但这迫使我在方法签名中添加"抛出异常"。无论如何,此方法都会引发异常。为什么我必须更改签名?
这取决于,如果你抛出检查异常,那么java编译器将强制你处理它,即你需要把它包含在方法签名中或在方法主体中处理它。
但是,如果您抛出未经检查的异常,则无需修改方法签名
我强烈建议你不要通过抛出RuntimeException
来解决这个问题。这些是严格意义上的JVM专利,使用一个只是为了避免声明抛出子句将是可怕的风格。
Java 异常的名称和目的(恕我直言)令人困惑。你应该坚持这样的想法,即从Exception
子类化的东西需要处理程序,而从Error
派生的东西不需要。忽略破坏规则的RuntimeException
,向酒吧里的同伴和 stackoverflow.com 上的随机人抱怨它应该被称为RuntimeError
和子类Error
(为了f**ks)。
如果你真的有一个条件,一个方法有一个 throws 子句声明一个Exception
但你现在有充分的理由抛出它,那么我建议你对 UnexpectedExceptionError
或 UnhandledExceptionError
进行子类Error
。
如果Exception
"不应该是可能的",请使用第一个 - 例如一个抽象的I/O方法,你知道它由(比如)内存中的字符串支持,并且尽管有接口声明,但不能真正抛出IOException
。
如果抛出Exception
会破坏您正在实现/覆盖的某些方法的签名,则使用第二个,这些方法无法修改以通告潜在的Exception
。
作为第三种方式,异常传播到run()
Runnable
方法是很自然的。在这些情况下,我建议将Exception
传递给某个监督者流程作为一种遗书,因为无论您扔出run()
什么,无论如何都会被忽略,您可能想做一些事情来识别Thread
的完全失败!
PS:如果你这样做是因为你懒惰,不想正确处理异常,那么你会被诅咒维护由具有相同态度的人编写的代码:)
在 Java 中,您已经选中了异常 - 这些异常必须由抛出方法声明 - 并且未选中,这不一定是。(然后有Error
的,但让我们暂时把它们放在一边)。
不详细介绍使用哪种异常策略,基本上您可以抛出任何异常,即 a 或从 RuntimeException
扩展的异常,而无需在您的方法上声明它。例如。你可以
void myMethod() { // no 'throws' declaration
try {
...
} catch (Exception e) {
throw new RuntimeException( SOME_CUSTOM_VARIABLE , e );
}
}
我将推荐这个SO线程和这篇博客文章,以便就该主题进行很好的讨论。
关于在throws
条款中用另一个例外替换异常的问题:我知道您的方法已经抛出了一些不是专门java.lang.Exception
的异常。在这种情况下,你大多不走运 - 你只能用相同或子类化的异常"替换"抛出的异常,否则你将不得不编辑/添加到throws
子句。
干杯