代码之家  ›  专栏  ›  技术社区  ›  lindelof

在不引发异常的情况下实例化异常是否可以?

  •  5
  • lindelof  · 技术社区  · 15 年前

    假设我有一个MyException类,它对异常进行子类化。当代码中出现错误时,我使用这个类来包含上下文信息。

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

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

    但是我的IDE(intellij-idea)警告我,在不抛出未检查异常的情况下实例化未检查的异常(本例中为illegalargumentexception)是不好的,但不会告诉我原因。

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

    5 回复  |  直到 14 年前
        1
  •  8
  •   Joel    15 年前

    你最好扔一个非法理由例外的例子,在这种情况下,这是为了:

    if (invalidInput())
             new IllegalArgumentException("Invalid argument " + x + ", expected ...");
    

    或者以其他方式扩展,illegalargumentexception而不是exception,如果您想用自定义属性增强它的话。

    public class MyIllegalArgumentException extends IllegalArgumentException {  
        public MyIllegalArgumentException(Object arg...) {    ....  } 
    }
    

    这两种情况都提供了一个更精简、更有意义的类模型。

    更新: 给出了您关于想要用抛出的异常提供上下文信息的意见-您可以通过将自定义异常对象作为标准异常构造的可丢弃参数来实现这一点,即翻转它,使: 不要将相关的标准异常包装在异常中,而是应该将异常包装在相关的标准异常中。 .

    if (invalidInput())
             new IllegalArgumentException("Invalid argument " + x + ", expected ...", new MyContextException(a,b,c));
    

    (其中A、B和C是您要传输的上下文的各种位)。 通过这种方式,您可以在代码中的所有点上重新使用一个有意义的、适当的异常,但您可以在处理/记录异常时向上传输您可能希望在堆栈中进一步使用的上下文信息。

        2
  •  2
  •   Buhb    15 年前

    你不会因为以自己的方式实例化一个异常而下地狱的。我确信警告是存在的,以确保您将异常用作异常,而不仅仅是任何对象。

    但是,您会因为MyException不是RuntimeException的子类而大吃一惊;)

        3
  •  2
  •   Andrzej Doyle    15 年前

    这一点也不坏。

    像大多数警告一样,它们是用来表示不太可能合法发生的情况,而不是错误地调用它们的人。最近的另一个例子是关于在局部变量上同步的警告;您不经常想这样做,而且很容易因为无意中这样做而导致并发混乱。

    Intellij只是警告您,通常会创建异常以立即抛出,因此如果您不这样做,它会标记出您的代码可能是意外行为。在你的情况下,你做的正是正确的,所以请随意忽略警告。(事实上,在我的项目中,结构意味着我经常创建异常,而不因各种原因而抛出异常,因此我将警告降级为intellij配置中的“info”级别)。

        4
  •  2
  •   user85421    15 年前

    这是一个 奇怪的 构造,但有一个解决方案 戏法 编译器。
    重写你的 invalidInput 投掷原子能机构的方法

        private void checkInput() throws IllegalArgumentException {
            if (...)
                throw new IllegalArgumentException();
    

    还有:

        try {
            checkInput();
        } catch (IllegalArgumentException ex) {
            throw new MyException(ex, arg1, arg2, ...);
        }
    
        5
  •  1
  •   Peter Lawrey    15 年前

    Intellij会告诉你原因。你只要看一下说明书就行了。

    此检查报告可丢弃实例化的任何实例,其中创建的可丢弃实际上从未被抛出。这通常是一个简单错误的结果。