我们什么时候应该创建自己的 Java 异常类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22698584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should we create our own Java exception classes?
提问by PedroD
From a good design/practice point of view, when should we create and use custom Java exception classes instead of the ones already predefined in Java?
从一个好的设计/实践的角度来看,我们什么时候应该创建和使用自定义的 Java 异常类而不是 Java 中已经预定义的类?
In some applications I see almost custom exception classes created, they make an effort to always use native Java exceptions. On the other hand, there are some applications that define custom exceptions for (almost) everything.
在一些应用程序中,我看到几乎创建了自定义异常类,它们努力始终使用本机 Java 异常。另一方面,有一些应用程序为(几乎)所有内容定义了自定义异常。
采纳答案by M. Abbas
From Best Practices for Exception Handling:
来自异常处理的最佳实践:
Try not to create new custom exceptions if they do not have useful information for client code.
如果没有对客户端代码有用的信息,尽量不要创建新的自定义异常。
What is wrong with the following code?
以下代码有什么问题?
public class DuplicateUsernameException extends Exception {}
It is not giving any useful information to the client code, other than an indicative exception name. Do not forget that Java Exception classes are like other classes, wherein you can add methods that you think the client code will invoke to get more information.
除了指示性异常名称之外,它不会向客户端代码提供任何有用的信息。不要忘记 Java Exception 类与其他类一样,您可以在其中添加您认为客户端代码将调用以获取更多信息的方法。
We could add useful methods to DuplicateUsernameException
, such as:
我们可以向 中添加有用的方法DuplicateUsernameException
,例如:
public class DuplicateUsernameException
extends Exception {
public DuplicateUsernameException
(String username){....}
public String requestedUsername(){...}
public String[] availableNames(){...}
}
The new version provides two useful methods: requestedUsername()
, which returns the requested name, and availableNames()
, which returns an array of available usernames similar to the one requested. The client could use these methods to inform that the requested username is not available and that other usernames are available. But if you are not going to add extra information, then just throw a standard exception:
新版本提供了两个有用的方法:requestedUsername()
,返回请求的名称,和availableNames()
,返回与请求的用户名相似的可用用户名数组。客户端可以使用这些方法来通知请求的用户名不可用而其他用户名可用。但是如果你不打算添加额外的信息,那么就抛出一个标准异常:
throw new IllegalArgumentException("Username already taken");
回答by Nikita
certainly when you expect to be able to programmatically handle an exception - ie it's easy to create separate catch statements for different exception types, ie:
当然,当您希望能够以编程方式处理异常时 - 即很容易为不同的异常类型创建单独的 catch 语句,即:
try{
buyWidgets();
}
catch(AuthenticationException ex)
{
promptForLogin();
}
catch(InsufficientFundsException ex)
{
promptToRefillAccount();
}
//let other types of exceptions to propagate up the call stack
On whether the above constitutes inappropriate use of exception for flow control
关于以上是否构成流量控制异常使用不当
While exceptions are more CPU-expensive than if-else statements (mainly due to cost of constructing a stack trace), cost is relative and should be assessed in the context of particular use case. Not every piece of code needs to be web-scale fast and some people find reading and testing conditionals more cumbersome. For example pretty much all transaction managers implement commit-rollback-retry idioms using exceptions. (Try writing a transaction retry aspect without catching an exception)
虽然异常比 if-else 语句更耗费 CPU(主要是由于构建堆栈跟踪的成本),但成本是相对的,应该在特定用例的上下文中进行评估。并非每段代码都需要快速扩展到网络规模,有些人发现阅读和测试条件更麻烦。例如,几乎所有事务管理器都使用异常实现提交-回滚-重试习惯用法。(尝试编写事务重试方面而不捕获异常)
Separately, one should adhere to separation of concerns principle: not every piece of code needs to deal with every possible condition. Whether not being logged in while buying widgets is an exceptional case really depends on the app and particular place in the app code base. For example, you could have a Service with operations for logged-in users. It makes no sense for methods in that service to deal with authentication - instead these methods would expect code earlier in the call chain to ensure user is authenticated, and thus simply throw exceptions if that is not so. Thus, for those methods being not logged in ISan exceptional case.
另外,应该坚持关注点分离原则:不是每一段代码都需要处理每一种可能的情况。是否在购买小部件时未登录是一种特殊情况,这实际上取决于应用程序和应用程序代码库中的特定位置。例如,您可以拥有一个对登录用户进行操作的服务。该服务中的方法处理身份验证没有意义 - 相反,这些方法需要调用链中较早的代码来确保用户通过身份验证,因此如果不是这样,则简单地抛出异常。因此,对于被未登录那些方法IS的例外情况。
回答by fge
from a good design/practice point of view, when should we create and use custom java exception classes instead of the ones already predefined in java?
从一个好的设计/实践的角度来看,我们什么时候应该创建和使用自定义的 java 异常类而不是已经在 java 中预定义的类?
When the existing exception names don't cover your need.
当现有的异常名称不能满足您的需求时。
Another design concern is to extend the "good" exception class; for instance, if you raise an exception related to I/O, you should ideally inherit IOException
; if the exception indicates a programmer error, you should inherit RuntimeException
(ie, make your exception unchecked).
另一个设计问题是扩展“好”异常类;例如,如果您引发与 I/O 相关的异常,则理想情况下应该继承IOException
; 如果异常表明程序员错误,您应该继承RuntimeException
(即,不检查您的异常)。
Raising custom exceptions also allows you to treat exceptions in a more precise manner; for instance, if you have defined FooException
inheriting IOException
, then you can have a special treatment for it:
引发自定义异常还可以让您以更精确的方式处理异常;例如,如果您定义了FooException
inheriting IOException
,那么您可以对其进行特殊处理:
try { ... }
catch (FooException e) { ... } // Catch it _before_ IOException!
catch (IOException e) { ... }
Also, exceptions are classes like any other, so you can add custom methods etc; for instance, Hymanson defines JsonProcessingException
which inherits IOException
. If you catch it, you can obtain location information of the parse error using .getLocation()
.
此外,异常与任何其他类一样,因此您可以添加自定义方法等;例如,Hymanson 定义JsonProcessingException
了继承IOException
. 如果捕捉到它,则可以使用 获取解析错误的位置信息.getLocation()
。
回答by dkatzel
I often create custom Exceptions if there is more information that I need to convey instead of just an error message.
如果我需要传达更多信息而不仅仅是错误消息,我经常创建自定义异常。
For example particular error codes or actual vs expected values. these can also have their own getters so you can programically retrieve these fields without having to parse the String message which could break if you ever change the text of the message. (Or translate it into a different language)
例如特定的错误代码或实际值与预期值。这些也可以有自己的 getter,因此您可以以编程方式检索这些字段,而无需解析 String 消息,如果您更改消息的文本,该消息可能会中断。(或将其翻译成其他语言)
If you make your own Exceptions, I would recommend extending the common JDK built in exceptions so your API can say throws IOException
but it really throws MycustomIOException
. that way users of your API don't have to know about your own custom versions unless they want to.
如果您创建自己的异常,我建议扩展常见的 JDK 内置异常,以便您的 API 可以说throws IOException
但它确实抛出MycustomIOException
. 这样您的 API 用户就不必知道您自己的自定义版本,除非他们想知道。
回答by Shailendra Singh
Its good to have custom exceptions in your application, one may be a top level custom exception for applications, others at the module/package levels. If you have some specific function/operation in app and you need let the user know if any exception occurred during the operation then better to add custom exception for that operation. It will be easy to debug/investigate the issues.
在您的应用程序中有自定义异常是件好事,一个可能是应用程序的顶级自定义异常,其他可能是模块/包级别的。如果您在应用程序中有一些特定的功能/操作,并且您需要让用户知道在操作过程中是否发生任何异常,那么最好为该操作添加自定义异常。调试/调查问题会很容易。
回答by GhostCat
You do so when using your own exception adds valueto your code base.
当使用您自己的异常为您的代码库增加价值时,您会这样做。
It is that simple. Value could be:
就是这么简单。价值可能是:
- catching on a higher level might be easier, for example when all your exception have a common base type
- your exception carry addition data (we include NLS keys in our own exceptions, so that a higher layer knows how to give messages to human users taking I18N into account)
- 捕获更高级别可能更容易,例如当您的所有异常都具有共同的基本类型时
- 您的异常携带附加数据(我们在自己的异常中包含 NLS 密钥,以便更高层知道如何将消息发送给人类用户并考虑 I18N)