简体   繁体   English

使用Java中的自定义异常类型包装异常是否有优势

[英]Is there an advantage to wrapping exceptions with Custom exception types in Java

I have a class XYZ whose public functions throw Exception s. 我有一个类XYZ其公共函数抛出Exception s。

I have been advised that all public functions exposed by XYZ should throw exceptions called XYZDataException or XYZSystemException . 我被告知XYZ公开的所有公共函数都应抛出名为XYZDataExceptionXYZSystemException异常。 So even if I get other exceptions within the public methods they need to be wrapped by these XYZException s. 因此,即使我在公共方法中得到其他异常,它们也需要被这些XYZException包装。

I have a couple of questions: 我有一些问题:

  1. What is the advantage of wrapping exceptions with XYZException? 使用XYZException包装异常有什么好处?
  2. What is the advantage of differentiating between System and Data exceptions? 区分系统和数据异常有什么好处?

To me it feels right to just throw whatever exception occurs without wrapping it further. 对我来说,只要抛出任何异常而不进一步包装它是正确的。

A lot of Exception handling depends on how you plan on extending it later on. 很多异常处理取决于您以后计划如何扩展它。 For example, if developer B came along and wanted to modify some of your code, it would be a lot easier if he understand what Exception meant what in which case. 例如,如果开发人员B出现并希望修改一些代码,那么如果他了解Exception在哪种情况下意味着什么,那将会容易得多。 In that case, having specific Exceptions makes more sense. 在这种情况下,具有特定的例外更有意义。

As to breaking up System and Data exceptions - a Data exception would basically be something that should be non-fatal that occurs because of bad data. 至于分解系统和数据异常 - 数据异常基本上应该是由于数据不良而发生的非致命异常。 A System exception would be because your System failed in some way. 系统异常是因为您的系统以某种方式失败。 Again, this all points to how you want to use it later on. 同样,这一切都指向了以后如何使用它。 If you want to use your code solely, and you don't care about how your exceptions come back out, then by all means, go with what is easiest at the time. 如果你想单独使用你的代码,并且你不关心你的异常如何回归,那么无论如何,请选择当时最简单的代码。

I have found that when working with other developers on a project, it is a lot easier for them to grasp what is going on when you subclass your Exceptions and throw them in specific cases. 我发现在与项目上的其他开发人员合作时,他们更容易理解当您将Exceptions子类化并在特定情况下抛出它们时发生的事情。

Hope this helps! 希望这可以帮助!

Yes, it means they can be explicitly caught by code that knows how to handle them. 是的,这意味着它们可以被知道如何处理它们的代码明确捕获。

for instance, imagine you had: 例如,想象你有:

class MyRecoverableException extends Exception {
   ...
}

You could then have code that can differentiate between them automatically, and react accordingly, such as: 然后,您可以拥有可以自动区分它们的代码,并做出相应的反应,例如:

try{
// ... do something ...
}catch(MyRecoverableException e) {
   // Recover
}catch(Throwable t) {
   // Log fatal reason, and exit gracefully.
}

Obviously how many you need is a problem to be solved by you, the application developer, but a clean separation can make all the difference when working out what went wrong, and subclassed exceptions can hold additional properties, used to pass pertinent information to handlers about the exceptional circumstances that brought them about. 显然,你需要多少是你应用程序开发人员需要解决的问题,但是在解决出错的地方时,一个干净的分离可以产生重大影响,而子类异常可以包含其他属性,用于将相关信息传递给处理程序带来他们的特殊情况。

Having a base type to extend from for your application/library never hurts either - if for no other reason than to allow separation of source when logging - but the exact hierarchy and complexity required beyond that depends entirely on the project. 从应用程序/库扩展的基本类型也不会受到任何伤害 - 如果没有其他原因,只允许在记录时允许分离源 - 但除此之外所需的确切层次结构和复杂性完全取决于项目。 Some designs have natural and obvious choices, some require a bit more forethought (and occasionally a bit of afterthought and refactoring). 有些设计有自然而明显的选择,有些需要更多的预见(偶尔会有一些事后的想法和重构)。

As usual, "it depends". 像往常一样,“它取决于”。 As a general rule it does not make sense to blindly create an exception hierarchy on a per-class basis. 作为一般规则,在每个类的基础上盲目地创建异常层次结构是没有意义的。 App-specific exceptions should group exceptions in a way meaningful to that particular app, so there might be a top-level exception, then sub-classed exceptions for things like the data layer, communication layer, utilities, whatever. 特定于应用程序的异常应该以对特定应用程序有意义的方式对异常进行分组,因此可能存在顶级异常,然后对数据层,通信层,实用程序等内容进行细分异常。

The advantage is that higher levels dealing with those exceptions are not exposed to the implementation details that generate those exceptions. 优点是处理这些异常的更高级别不会暴露于生成这些异常的实现细节。 Also, perhaps to a lessor degree, exceptions may be grouped more meaningfully (is it relevant that it was an IOException, or is it enough to know there was a problem writing to whatever output store you're using). 此外,也许在较小的程度上,异常可以更有意义地分组(它是IOException的相关性,还是足以知道写入您正在使用的任何输出存储器时存在问题)。

Another great advantage is that app-specific information may be captured in the custom exceptions. 另一个很大的优点是可以在自定义例外中捕获特定于应用程序的信息。 Things like user IDs, account numbers, etc.--any application state--which must be stored as part of a string message in a "stock" exception may be assigned to a property. 用户ID,帐号等等 - 任何应用程序状态 - 必须作为字符串消息的一部分存储在“库存”异常中,可以分配给属性。 This may avoid random parsing issues if you actually do anything with the exceptions or try to trace through a particular event stream. 如果您实际对异常执行任何操作或尝试跟踪特定事件流,则可以避免随机解析问题。

According to msdn : 根据msdn

To wrap an exception, you specify it as the inner exception of a new exception and then throw the new exception. 要包装异常,请将其指定为新异常的内部异常,然后抛出新异常。 This practice should be used only in situations where the original exception is not meaningful to the person who receives the exception, or the call stack for the exception is misleading or uninteresting. 这种做法只应在原始异常对接收异常的人没有意义的情况下使用,或者异常的调用堆栈具有误导性或不感兴趣。

Suppose method M1 is documented as throwing an exception of type X when some condition occurs. 假设方法M1被记录为在某些条件发生时抛出类型X的异常。 M1 calls method M2, which happens to throw an exception of type X which M1 is not prepared to handle. M1调用方法M2,这恰好抛出了M1未准备处理的类型X的异常。 If M1 doesn't catch the exception from M2, the caller is unlikely to figure out that the exception thrown out of M1 isn't an X thrown by M1, but is instead an X thrown by M2, and its practical meaning and implications may be very different. 如果M1没有捕获到M2的异常,则调用者不太可能发现M1抛出的异常不是M1抛出的X,而是M2抛出的X,其实际意义和含义可能非常不同。 Having M1 throw an exception of a type which will never be thrown by M2 may avoid this issue (though there could still be trouble if M2 could call M1 on some other object). 让M1抛出一个永远不会被M2抛出的类型的例外可以避免这个问题(尽管如果M2可以在某个其他对象上调用M1,仍然会有麻烦)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM