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

yeg*_*256 31 java design-patterns exception-handling

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

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

哪个选项更好?

Ade*_*ari 16

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

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


Ste*_*n C 10

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

为什么你觉得有必要这样做,因为(显然)没有其他人这样做?我希望你不仅仅是为了"创新".

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

  • @Stephen C:不,这真的是个好主意.让我们稍微绕道而行:在java.util.HashMap中,你有一个名为Entry的内部类.为什么你认为这是一个内在阶级?因为它与HashMap密切相关,所以在HashMap的上下文之外无用,如果仍然使用它可能会产生误导.将其嵌入HashMap内部还可以在一个"单元"中创建完整的打包数据结构.同样可以申请例外. (4认同)
  • 是的,这就是这种例外的目的(你只是定义了它) - 使设计不可重复使用.当我们想要保持与类密切相关的异常(没有任何重用能力)时 - 使其成为静态内部.说得通? (3认同)
  • 从Apache Lucene 3.5看一下这个类:[org.apache.lucene.search.BooleanQuery.TooManyClauses](http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/api/all/org/apache /lucene/search/BooleanQuery.TooManyClauses.html) (2认同)
  • 好吧,我认为只有从一个class_抛出异常才有意义.在这种情况下,它应该被定义为静态内部类.删除课程时 - 异常也会消失.换句话说,它们将"紧密耦合". (2认同)

Ben*_*Ben 8

我绝对可以想到这样的情况:我更喜欢异常是一个静态内部类,而不仅仅是同一个包中的一个类.

不这样做的原因似乎是:

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

我完全没有发现任何一个论点令人信服.

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

但即使没有"走极端"的观点,也要考虑一个旨在传达该类Foo被错误输入的例外情况.如果我打电话给它Foo.InvalidInput,名字很短,并且Foo不可能错过联想.如果我把它放在Foo课外并调用它FooInvalidCriteria,那么Bar无论如何我都不能从类中重用它,而不改变它的名字(相当于改变它的位置).

但最糟糕的是,如果我把它留在外面,Foo并保持其名称一般InvalidInput.然后当我后来意识到Bar可能也有无效输入并让它开始抛出这个异常.一切都编译并运行良好,只是现在所有捕获InvalidInput并假设它们正在处理错误的地方Foo现在也可以处理错误,Bar如果Foo碰巧在Bar内部使用可能导致抛出此异常的方式.这很容易导致代码破坏.

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

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