Java 我应该什么时候创建一个新的异常类

Java 我应该什么时候创建一个新的异常类,java,exception,Java,Exception,我注意到许多Java异常类只在类的名称上有所不同,并且没有添加任何新功能。例如,大多数异常似乎只是覆盖了异常()或异常(字符串消息)。这违背了继承的原则,即:-继承以添加新功能 创建新异常类的一些好理由是什么?您可以按类型捕获异常,并且拥有与基本异常类相同的特定类型的异常可以精确地处理异常 我认为它确实通过增加异常处理代码的特殊性直接添加了新功能。异常是一种特殊情况。在他们的情况下,继承不是添加新功能,而是添加新的错误类。这使您的代码能够捕获特定类型的错误,同时忽略其他错误 假设你正在写一个大项

我注意到许多Java异常类只在类的名称上有所不同,并且没有添加任何新功能。例如,大多数异常似乎只是覆盖了异常()或异常(字符串消息)。这违背了继承的原则,即:-继承以添加新功能


创建新异常类的一些好理由是什么?

您可以按类型捕获异常,并且拥有与基本异常类相同的特定类型的异常可以精确地处理异常


我认为它确实通过增加异常处理代码的特殊性直接添加了新功能。

异常是一种特殊情况。在他们的情况下,继承不是添加新功能,而是添加新的错误类。这使您的代码能够捕获特定类型的错误,同时忽略其他错误


假设你正在写一个大项目。您有一个数据组件和一个显示组件。它们都可能以各种方式失败,您希望为这些失败抛出异常。不过,显示组件并不关心数据组件引起的异常,反之亦然。如果所有类都抛出了异常,那么就没有办法找出异常的来源。但是,如果您使用
DataException
graphicsceception
Exception
进行子类化,即使它们没有添加新功能,您现在也可以抛出并捕获这些特定类型的异常,也就是说,图形组件可以捕获
GraphicsException
,而不必处理数据异常。

当API的用户可能需要有条件地捕获它时,您可以添加一个新的异常类(或者,为了在
中指定不同的特定类型,抛出
)。

发生此重命名是为了消除歧义。已发生的错误。e、 g

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和一个EOFEException。您可能希望以不同的方式处理这些情况。如果您只有IOException,那么您必须执行类似于查看错误消息的操作,然后执行If/else语句来确定实际错误是什么,以便向用户显示合理的消息。使用异常的层次结构,您可以更轻松地处理这些情况。

在本例中,继承添加的功能与catch语句有关,它可以根据类型进行区分。通常,按类型区分子类被认为是一种不好的做法,但异常处理是一种异常


它肯定会导致一些奇怪的情况(如多个具有相同逻辑的catch语句),正如您在按类型区分事物时所期望的那样,但这是语言的一个限制。

我建议您阅读本手册第9章的全部或大部分内容。特别是第60项:“支持使用标准异常”和第61项:“抛出适合抽象的异常”


编辑1:或在第一版中。

为任何类型创建异常都是愚蠢的。也许您应该为不同的层(DAO、服务等)或不同的操作(创建记录、复制记录等)创建一个异常。

如果您需要或希望将特定错误情况与代码中的其他错误区分开来,那么将适当的异常子类化是有意义的。您不需要查看错误消息来确定出了什么问题-这仅适用于人眼


还要注意的是,一个正确命名的异常可能足以让维护人员推断出在诊断堆栈跟踪时出现了什么问题。一个典型的例子是BoundsException的ArrayOutOfBoundsException。

不要忘记继承(例如MyNumericDataException扩展了MyDataException)让您的异常处理体系结构可以非常干净地将各种类型的异常分组在一起。使用子类来区分异常原因似乎与继承的使用背道而驰。还有其他方法可以识别类型。然而,真正的问题是语言的局限性,即catch/throw的固有结构是基于类类型进行区分的。是的,但是Java类的单一继承自然适合建立抽象层次结构。因此,允许对异常的响应程度,即为更高级别的抽象汇总异常。。。令人困惑在Java中,“检查”已检查的异常是由编译器完成的,而不是由您的代码完成的。稍微吹毛求疵,但是“FileNotFoundException”,并且“应该是”FileNotFoundException,或者“应该是”,因为一次只能发生一个异常。确实如此,但是您可能会错过所有3个捕获,或者暗示您只需要一个。。。抛硬币:-)继承仅更改异常的名称不是最佳做法。然而,这样做是为了创建一个异常层次结构,在不同的抽象层上提供响应的程度,这是一个很好的实践。换句话说