可以在不抛出异常的情况下实例化异常吗?

时间:2009-12-02 11:00:58

标签: java

假设我有一个MyException类,它继承了Exception。我正在使用此类在我的代码中发生错误时包含上下文信息。

我通常用它来包装一个“标准”异常类。例如,如果在输入验证期间发生错误,我将执行类似

的操作
if (invalidInput())
  throw new MyException(new IllegalArgumentException(), arg1, arg2, ...);

但我的IDE(Intellij IDEA)警告我,实例化一个未经检查的异常(本例中为IllegalArgumentException)而不抛出它是不好的,但不告诉我原因。

那么在不抛出异常的情况下实例化异常是多么有罪?我将去哪个地狱圈?

5 个答案:

答案 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实际上从未被抛出。大多数情况下,这是一个简单错误的结果。