【问题标题】:Throw IOException instead of Exception抛出 IOException 而不是 Exception
【发布时间】:2014-05-05 19:55:37
【问题描述】:

我有 method1() 在整个代码中从许多其他方法调用。这是方法的签名:

 public void method1(final Properties properties) throws IOException {}

所有调用此方法的方法也会抛出 IOException。

method1() 中的实际代码发生了变化,所以现在它不再抛出 IOException 而是抛出一些扩展 Exception 的其他异常,并且 不再 IOException。

我不想更改所有调用 method1() 的方法的签名。

是否可以创建 IOException 并仍然从 method1() 抛出 IOException 并因此调用 method1() 的方法?

如下所示:

 Try {
  // code
 } catch (Exception e) {
   throw new IOException(e.getCause());
 }

【问题讨论】:

  • 这可行,但对我来说它看起来很脏,因为您丢失了实际抛出的异常类型所携带的信息。
  • 当我有 e.getCause() 和 e.getMessage() 时,他们不给我实际的异常以及与该异常相关的信息吗?
  • 我宁愿直接使用Throwable构造函数:new IOException(e),所以当你的ioexception被捕获时,可以使用myIOException.getCause()检索根异常。此外,这将在堆栈跟踪中打印一个caused by 块,这将有助于调试
  • 如果method1 的所有调用者也抛出IOException 他们似乎没有处理它,那么声明异常毫无意义。如果不期望调用者处理method1 抛出的内容,为什么不抛出RuntimeException 的合适子类型?
  • 调用者自己处理或抛出自己的 IOException。你是对的,我可以更改所有方法的签名 - 包括 method1() 来抛出自定义 exp。相反,但想避免与此相关的实际代码更改。经验。但是,method1() 抛出的问题不会也不应该被处理,它最终会出现在错误日志中。

标签: java exception ioexception


【解决方案1】:

,你不应该这样做,因为你会混淆所有其他开发人员阅读你的代码或阅读堆栈跟踪。

从软件设计的角度来看,错误发生得更早。 如果您的代码类似于 API 并被其他人使用,您最好使用自定义异常并将 IOException 包装为根本原因。

如果你有完整的源代码,你应该重构源代码并添加另一个异常签名。

【讨论】:

    【解决方案2】:

    您需要将原始异常保存为原因,这样您就不会丢失原始消息或堆栈跟踪。在您的代码示例中调用 e.getCause() 会跳过您捕获的异常并获取 its 原因,这看起来很可疑。

    另外,最好指定方法捕获的特定异常,而不是使用包罗万象的异常类型。捕获异常会导致捕获之前未捕获的诸如 NullPointerExceptions 之类的东西。

    这里最好的做法是将您的方法抛出的异常更改为自定义类型,该类型不会让实现细节泄露给调用者。您的方法签名应更改为

    public void method1(final Properties properties) throws SomeCustomException {
        try {
            .... // do whatever
        } catch (AException | BException | CException e) {
            throw new SomeCustomException(e);
        }
    }
    

    【讨论】:

    • 我认为这样做是一个非常糟糕的主意。没有人会明白为什么会为 DatabaseException 引发 IOException(如果从文件系统迁移到数据库)。
    • @Christian:是的,我最初误解了这个问题。
    【解决方案3】:

    这在技术上是可行的。

    然而,捕捉ExceptionThrowable 几乎每次都是一个坏主意(就像抛出它们一样),因为除了RuntimeExceptions 之外,您还会捕捉所有其他异常。

    如果您可以更改所有调用类的代码(即您没有开发框架/库),您应该这样做。因为我假设您的意思是 method1() 现在会抛出更具体的类型。

    您也可以考虑抛出一个不需要捕获的子类型RuntimeException,对于无法纠正的错误(例如错误的配置)是一个好主意。 (参见 Robert Martin 的Clean Code

    【讨论】:

    • 对了,现在抛出的异常是:com.google.api.ads.common.lib.exception.OAuthException AND com.google.api.ads.common.lib.exception.ValidationException 我可以只捕获这两个异常而不是异常。我们也有自定义异常,问题是我不想更改所有调用 method1() 的方法的签名以抛出任何其他异常而不是 IOException。
    • 如果您在一个 IDE 中提供所有调用类,那通常没什么大不了的......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2012-06-12
    • 2014-03-24
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多