我想知道如何知道创建和抛出检查异常或未检查异常。
例如,我有一个服务,它接受一些数据并在使用它之前验证它。在验证过程中,某个字段不符合规则,我想抛出一个异常,比如ValidationException()。我怎么知道应该检查还是不检查呢?
在另一种情况下,我从我的代码中调用外部web服务,例如谷歌股票api。假设超时时间是3秒。如果时间到期,我想抛出一个异常,说backendexeption()。我怎么知道它应该是一个检查异常还是一个未检查异常呢?
可能有不同的意见,但我认为区别在于调用者应该如何处理该异常:
- 如果你想确保调用者通过做一些事情(记录,试图恢复等)或重新抛出处理异常,然后使用检查异常。一个例子是
ValidationException
:如果数据无效,调用者应该处理它,例如,通过告诉某人修复数据或尝试其他方法。(注意,可能存在未检查的验证异常,例如javax.validation.ValidationException
。让这些未检查可能有各种各样的原因,例如,如果一个框架不允许/支持检查异常,或者如果一些中央处理程序无论如何都会捕获它们,所以开发人员不必麻烦。 - 如果你不想强迫调用者处理通常不应该被抛出的异常(例如编程错误等),请使用未检查的异常。这方面的一个例子可能是总是可怕的
NullPointerException
:它不应该发生,你想使用的东西是空的,所以它可能被认为是一个编程错误。如果某些东西可以为空,但不应该为空,则可能需要使用检查异常。
注意,一些库/方法使用IllegalArgumentException
,这是一个未检查的异常。如果抛出此异常,通常是编程错误,因为方法的契约(例如参数值不能为负)被违反,调用者应该修复代码或自己做一些检查。
另一种观点可能是:在某些情况下是否期望抛出异常?预期异常(仍然意味着发生了某种错误)将被检查异常,因为这样你就可以与调用者沟通,他应该期望在某些情况下抛出这些异常(例如,如果数据无效)。如果异常是意外的,你不应该强迫调用者处理这样的异常,因为你根本不希望它被抛出——因此它将是一个未检查的异常。
根据Joshua Bloch, Book Effective Java, Item 58用一行总结。经验法则是对可恢复的条件使用检查异常,对编程错误使用运行时异常。