从良好的设计/实践角度来看,我们何时应该创建和使用自定义java异常类而不是已经在java中预定义的异常类?
在某些应用程序中,我看到几乎没有,甚至没有创建自定义异常类,他们总是努力使用本机java异常。另一方面,有些应用程序为所有内容定义自定义异常。
最佳做法是什么?
谢谢!
答案 0 :(得分:37)
来自Best Practices for Exception Handling:
如果客户端代码没有有用的信息,请尽量不要创建新的自定义例外。
以下代码有什么问题?
public class DuplicateUsernameException extends Exception {}
除了指示性异常名称之外,它没有向客户端代码提供任何有用的信息。不要忘记Java Exception类与其他类一样,您可以添加您认为客户端代码将调用的方法以获取更多信息。
我们可以向DuplicateUsernameException
添加有用的方法,例如:
public class DuplicateUsernameException
extends Exception {
public DuplicateUsernameException
(String username){....}
public String requestedUsername(){...}
public String[] availableNames(){...}
}
新版本提供了两种有用的方法:requestedUsername()
,返回请求的名称; availableNames()
,返回与请求的用户名类似的可用用户名数组。客户端可以使用这些方法来通知所请求的用户名不可用,并且其他用户名可用。但是,如果您不打算添加额外信息,则只会抛出标准异常:
throw new IllegalArgumentException("Username already taken");
答案 1 :(得分:10)
从良好的设计/实践角度来看,我们何时应该创建和使用自定义java异常类而不是已经在java中预定义的异常类?
当现有的例外名称不能满足您的需求时。
另一个设计问题是延长" good"例外类;例如,如果你引发了与I / O相关的异常,你应该理想地继承IOException
;如果异常表明程序员错误,则应继承RuntimeException
(即,取消选中您的异常)。
提高自定义异常还允许您以更精确的方式处理异常;例如,如果您已定义FooException
继承IOException
,那么您可以对其进行特殊处理:
try { ... }
catch (FooException e) { ... } // Catch it _before_ IOException!
catch (IOException e) { ... }
此外,异常是与其他类似的类,因此您可以添加自定义方法等;例如,杰克逊定义JsonProcessingException
继承IOException
。如果您抓住它,则可以使用.getLocation()
获取解析错误的位置信息。
答案 2 :(得分:6)
当你期望能够以编程方式处理异常时 - 也就是说,为不同的异常类型创建单独的catch语句很容易,例如:
try{
buyWidgets();
}
catch(AuthenticationException ex)
{
promptForLogin();
}
catch(InsufficientFundsException ex)
{
promptToRefillAccount();
}
//let other types of exceptions to propagate up the call stack
关于上述内容是否构成对流量控制的异常使用
虽然异常比if-else语句更耗费CPU(主要是由于构建堆栈跟踪的成本),但成本是相对的,应该在特定用例的上下文中进行评估。并非每一段代码都需要快速的网络规模,有些人发现阅读和测试条件更加繁琐。例如,几乎所有事务管理器都使用异常实现commit-rollback-retry惯用法。 (尝试编写事务重试方面而不捕获异常)
另外,应该遵循关注点分离原则:并非每一段代码都需要处理所有可能的条件。是否在购买小部件时没有登录是一个特例,实际上取决于应用程序和应用程序代码库中的特定位置。例如,您可以拥有一个服务,其中包含已登录用户的操作。对于该服务中的方法处理身份验证没有任何意义 - 相反,这些方法会期望调用链中的代码能够确保用户通过身份验证,因此如果不是这样,则只会抛出异常。因此,对于那些没有登录 IS 的方法,这是一种例外情况。
答案 3 :(得分:2)
您可以在使用自己的异常时将 value 添加到代码库中。
就是这么简单。值可以是:
答案 4 :(得分:1)
如果有更多信息需要传达而不仅仅是错误信息,我经常创建自定义例外。
例如特定错误代码或实际与预期值。这些也可以有自己的getter,这样你就可以以编程方式检索这些字段,而不必解析String消息,如果你改变了消息的文本,它可能会破坏。 (或将其翻译成其他语言)
如果您制作自己的例外,我建议您扩展常见的JDK内置异常,这样您的API可以说throws IOException
,但它确实会引发MycustomIOException
。这样,您的API用户就不必了解您自己的自定义版本,除非他们愿意。
答案 5 :(得分:1)
在应用程序中拥有自定义异常非常好,一个可能是应用程序的顶级自定义异常,另一个可能是模块/包级别的自定义异常。如果您在应用程序中有一些特定的功能/操作,并且您需要让用户知道在操作期间是否发生任何异常,那么最好为该操作添加自定义异常。调试/调查问题很容易。