公共类与公共静态内部类的异常

时间:2010-11-15 10:50:16

标签: java design-patterns exception-handling

我有两个选项(技术上是相同的,据我所知)来声明仅从特定类com.XXX.Foo抛出的自定义异常类:

  • 作为套餐中的公共类:com.XXX.CustomException
  • 作为公共静态内部类:com.XXX.Foo.CustomException

哪个选项更好?

5 个答案:

答案 0 :(得分:15)

如果异常非常特定于Foo类,我不介意将其保留为public嵌套类。无论什么时候将它提取出来,只需将其解压缩即可。

在一般实践中,我从未见过为Exception定义的任何嵌套类。我也不知道Java API中是否存在一个。

答案 1 :(得分:10)

在我10年的Java经验中,我不记得遇到过将公共异常类定义为静态内部类的API。我不能给你一个特定的理由说明为什么这样做是个坏主意,但它肯定会使你的代码异常

为什么你觉得有必要这样做,因为(显然)没有其他人这样做?我希望你不只是做到“创新”。

(顺便说一句,我知道一些着名的Java API使用公共静态内部类和接口来处理其他事情。我在这里专门讨论异常类的情况。)

答案 2 :(得分:8)

我绝对可以想到我将偏好异常作为静态内部类而不仅仅是同一个包中的类的情况。

不这样做的原因似乎是:

  • 将异常耦合到抛出它的类使得在其他上下文中重用是不合适的
  • 没有其他人这样做

我根本没有找到任何一个论点。

首先,为什么这个假设的未来重复使用机会会出现在同一个包中?这个论点得出的结论是,我们应该在包层次结构中尽可能高地放置所有异常类,这样当我们发现重用相同异常的未来机会时,我们不必引入对最初定义的位置的依赖。

但是,即使没有“走极端”的观点,也要考虑一个例外,旨在传达类Foo被错误输入。如果我将其称为Foo.InvalidInput,则名称很短,与Foo的关联不可能错过。如果我将它放在Foo类之外并将其命名为FooInvalidCriteria,那么无论如何我都无法在类Bar中重用它,而无需更改其名称(相当于更改其位置)。 / p>

但最糟糕的是,如果我将其保留在Foo之外,并将其名称保持为InvalidInput。然后当我后来意识到Bar也可能有无效输入并让它开始抛出此异常。所有内容都可以编译并运行正常,但是现在所有正在捕获InvalidInput并假设他们正在处理来自Foo的错误的地方现在也可以处理来自Bar的错误,如果Foo发生的话在内部使用Bar的方式可能会导致抛出此异常。这很容易导致代码破坏。

现实情况是,以前设想的异常是专门指示一个类中出现的情况并将其重新用作一般错误类的是接口更改,而不仅仅是内部实施变革。为了正确地执行此操作,您必须重新访问捕获异常的所有站点并确保它们仍然正确,因此让编译器告诉您所有使用站点(因为您必须更改)名称和/或导入路径)是一件好事。您可能创建静态内部类的任何异常都不适合在其他上下文中重用,无论您是否真正将其作为内部类。

至于第二个点......“没有其他人这样做”从不承担任何责任。要么它真的是错误的,所以还有其他原因不这样做,所以“没有其他人这样做”的论点是不必要的。或者事实并非如此。并不是说这个特殊的例子甚至会非常复杂和难以理解,所以即使是“它出乎意料,所以即使在理论上这是一个好主意,人们也会遇到麻烦”这一论点非常强烈。

答案 3 :(得分:3)

我更喜欢同一个包中的(不一定是公共的)类,因为包是描述业务模型的逻辑类组,该异常属于技术部分。

用户将立即看到当他查看包时出现异常,并且不需要读取类foo的文件,这对于维护和清晰度/可读性/理解原因更好。定义自定义异常并告诉API用户它是非常好的!

我只使用内部类,因为它显然是所讨论类的私有内容。

尽管如此,我们在这里谈的是一个主要的传统问题!

答案 4 :(得分:-3)

作为内部类的异常通常是一个坏主意,因为从本质上讲,它们可能通过各种级别提升,即使在简单的体系结构中也是如此。引发的异常类必须从其包含的类中引用,如果类路径未知该类,则可能会发生类似ClassCastException的错误。