我注意到一些Java异常类仅在类的名称上有所不同,并且不添加任何新的功能。例如,大多数例外似乎都会覆盖Exception() or Exception(String message)
。这违背了继承原则,即: - 继承添加新的功能。什么时候应该创建一个新的异常类
创建一个新的Exception类有什么好的理由?
我注意到一些Java异常类仅在类的名称上有所不同,并且不添加任何新的功能。例如,大多数例外似乎都会覆盖Exception() or Exception(String message)
。这违背了继承原则,即: - 继承添加新的功能。什么时候应该创建一个新的异常类
创建一个新的Exception类有什么好的理由?
异常是一种特殊情况。在他们的情况下,继承不是添加新的功能,而是添加新的错误类。这可以让你的代码抓住特定类型的错误而忽略其他错误。
假设你正在编写一个大型项目。你有一个Data组件,并且你有一个Display组件。他们都可能以各种方式失败,并且你想为这些失败抛出异常。 Display组件不关心Data组件产生的异常,反之亦然。如果所有的类只是抛出了Exception
,那么就没有办法找出异常来自哪里。但是,如果您将Exception
与DataException
和GraphicsException
一起继承,即使它们没有添加新功能,现在也可以抛出并捕获这些特定类型的异常,即图形组件可以捕获GraphicsException
,而不必处理数据异常。
不要忘记继承(例如MyNumericDataException扩展MyDataException)可以让您的异常处理架构真正干净地将各种类型的异常组合在一起。 – 2009-12-31 18:01:04
那么,使用子类来区分异常原因似乎对继承的使用不直观。还有其他方法可以识别类型。然而,真正的问题是语言的限制,catch/throw的方式固有地根据类的类型进行区分。 – VDev 2009-12-31 18:49:26
是的,但Java类的单一继承非常适合建立抽象层次结构。因此,允许对异常做出反应的程度,即为更高层次的抽象卷起例外。 – harschware 2009-12-31 18:57:13
您可以通过类型捕获异常,并且具有与基本Exception类别相同的特定类型的异常,这使您能够在异常处理中做到精确。
我认为它通过增加异常处理代码的特异性直接增加了新的功能。
当API的用户可能需要有条件地捕获它时(或者checked exceptions在throws
中指定了不同的特定类型),可以添加一个新的异常类。
括号内容是......令人困惑。在Java中,检查异常的“检查”是由编译器完成的,而不是由你的代码完成的。 – 2009-12-31 18:31:11
我会重申那一点。 – 2009-12-31 18:48:53
此重命名发生以消除歧义wrt。发生的错误。例如
Foo getFoo() throws FooNotFoundException
将是明确的指示Foo
不能被发现,而不是(什么?)一些非法状态,或数据库连接错误或相似的,你可以选择代码(或没有)为特别是错误。如果您选择抛出更通用的异常,则不太清楚(编程)发生了什么。
这是不好的形式,只是赶上任何异常,因为你不仅不知道它来自哪里,但你可能会防止自己在发生错误时正确处理错误。如果你只是捕获任何类型的异常并以相同的通用方式处理它,那么你可能会隐藏软件中的其他问题,甚至引入新的异常。所以,从技术上说,子类异常确实增加了新功能。
如果您希望为特定条件提供错误处理,请使用新的异常类型。看看java.io.IOException的,你会看到下面的子类:
ChangedCharSetException
CharacterCodingException
CharConversionException
ClosedChannelException
EOFException
FileLockInterruptionException
FileNotFoundException
FilerException
HttpRetryException
IIOException
InterruptedIOException
InvalidPropertiesFormatException
JMXProviderException
JMXServerErrorException
MalformedURLException
ObjectStreamException
ProtocolException
RemoteException
SaslException
SocketException
SSLException
SyncFailedException
UnknownHostException
UnknownServiceException
UnsupportedDataTypeException
UnsupportedEncodingException
UTFDataFormatException
ZipException
假设你想从文件中读取,你可以得到一个通用的IOException异常,一个FileNotFoundException异常,和EOFException类。你可能想要以不同的方式处理每一种情况。如果你只有IOException,你将不得不做一些事情,比如查看错误消息,然后执行if/else语句来确定实际错误是什么,以便向用户显示合理的消息。有了例外的层次结构,您可以更轻松地处理这些情况。
在这种情况下,继承添加的功能与catch语句有关,它可以按类型区分。通常按类型区分子类被认为是不好的做法,但是异常处理就是一个例外。
它肯定会导致奇怪的情况(例如具有相同逻辑的多个catch语句),正如您按照类型区分事物时所期望的那样,但这是语言的限制。
我推荐阅读Effective Java第9章的全部或大部分内容。特别是第60项:“赞成使用标准例外”和第61项:“投入适用于抽象的例外”。
编辑1:或Items 42 and 43在第一版。
为任何类型创建一个例外是非常愚蠢的。也许你应该为不同的层(DAO,Service等)或不同的操作(创建记录,重复记录等)创建一个异常。
如果您需要或想要区分特定的错误情况与代码中的其他错误,那么对适当的异常进行子类化是有意义的。你应该不是需要偷看错误信息,以确定出了什么问题 - 这只适用于人眼。
另外请注意,一个正确命名的异常可能足以让维护人员的眼睛推断出当诊断堆栈跟踪时出了什么问题。一个典型的例子是ArrayOutOfBoundsException。
继承只改变一个例外的名称是不是一个最佳实践恕我直言。但是,这样做可以创建一个异常层次结构,以便在各个抽象层上提供响应度,这是一种很好的做法。换句话说,创建新的Exception类有充足的理由和不好的理由! – harschware 2009-12-31 19:00:04