假设我有一个MyException类,它继承了Exception。我正在使用此类在我的代码中发生错误时包含上下文信息。
我通常用它来包装一个“标准”异常类。例如,如果在输入验证期间发生错误,我将执行类似
的操作if (invalidInput())
throw new MyException(new IllegalArgumentException(), arg1, arg2, ...);
但我的IDE(Intellij IDEA)警告我,实例化一个未经检查的异常(本例中为IllegalArgumentException)而不抛出它是不好的,但不告诉我原因。
那么在不抛出异常的情况下实例化异常是多么有罪?我将去哪个地狱圈?
答案 0 :(得分:8)
你可能最好抛出一个IllegalArgumentException实例,在这种情况下它就是它的用途:
if (invalidInput())
new IllegalArgumentException("Invalid argument " + x + ", expected ...");
或者以其他方式扩展,IllegalArgumentException而不是Exception,如果你想用自定义属性来增强它。
public class MyIllegalArgumentException extends IllegalArgumentException {
public MyIllegalArgumentException(Object arg...) { .... }
}
这两种情况都提供了一种更精简,更有意义的课堂模式。
<强>更新强> 鉴于您希望通过抛出的异常提供上下文信息,您可以通过将自定义异常对象作为标准异常构造函数的Throwable参数提供,即将其翻转为:而不是将相关的标准异常包装在您的例外,您应该将您的例外包装在相关的标准例外中。
if (invalidInput())
new IllegalArgumentException("Invalid argument " + x + ", expected ...", new MyContextException(a,b,c));
(其中a,b&amp; c是您要传输的各种上下文位)。 这样你(重新)使用一个有意义的&amp;在代码中的所有点处都是适当的异常,但是在处理/记录异常时,您可以传输可能需要在堆栈中使用的上下文信息。
答案 1 :(得分:2)
你不会以实现方式来实例化异常。我确定警告是为了确保您将例外用作例外,而不仅仅是任何对象。
但是,如果让MyException不是RuntimeException的子类,你会下地狱;)
答案 2 :(得分:2)
这一点都不错。
与大多数警告一样,他们在那里表示不太可能合法发生的情况,而不是错误地调用它们的人。关于SO的另一个最近的例子是关于同步局部变量的警告;通常你不想这样做,并且很容易通过不经意的方式搞乱并发性。
IntelliJ只是警告你通常会创建异常以便立即抛出,所以如果你不这样做,它会标记你的代码可能意外行为。在你的情况下,你正在做正确的事情,所以随意忽略警告。 (实际上在我的项目中,结构意味着我经常创建异常而不会因各种原因抛出异常,所以我将警告降级为IntelliJ配置中的“info”级别。)
答案 3 :(得分:2)
这是一个奇怪的构造,但有一个技巧编译器的解决方案。
重写你的invalidInput
方法以抛出IAE
private void checkInput() throws IllegalArgumentException {
if (...)
throw new IllegalArgumentException();
和:
try {
checkInput();
} catch (IllegalArgumentException ex) {
throw new MyException(ex, arg1, arg2, ...);
}
答案 4 :(得分:1)
IntelliJ确实告诉你原因。您只需阅读检查说明即可。
此检查报告Throwable实例化的任何实例,其中创建的Throwable实际上从未被抛出。大多数情况下,这是一个简单错误的结果。