假设我正在设计一个用于存储密码的API。根据Effective Java,使用throw子句来显示已检查的异常是一个好主意,但是通过使用抛出SQLException的throw子句(这是一个经过检查的异常),我将揭示我的API的底层实现细节,因此我将无法在稍后阶段更改我的API的实现细节。抛出检查异常的一个优点是使用API的程序员应该能够以他们选择的方式处理异常。我应该选择这两种方法中的哪一种,添加一个throw子句来揭示实现或隐藏它或使用不同的方法?
答案 0 :(得分:8)
您的动机是正确的,因为没有“泄漏”SQLException
给您班级的用户。
您使用SQL的事实可以被视为实现细节。您甚至可以将SQL持久性替换为以后的内存,并且此更改不应影响您的类的用户。
如果您倾向于使用已检查的异常,我会定义您自己的异常类型(例如,PasswordStoreException
- 只是一个示例名称)。您可以使用它来包装抛出的原始异常,例如:
try {
// do whatever
} catch (SQLException ex) {
throw new PasswordStoreException(ex);
}
答案 1 :(得分:3)
答案 2 :(得分:2)
捕获SQLException,并将其包装到您自己的异常中:
try {
// JDBC code
}
catch (SQLException e) {
throw new MyException("Error persisting the secret", e); // choose a better name, of course
}
此异常是应该是已检查的异常还是运行时异常取决于调用者可以对其执行的操作。如果它是可恢复的(我认为,这不是这种情况),它应该是一个经过检查的例外。如果它不可恢复(调用者只能显示错误消息),那么它应该是运行时异常。
如果是经过检查的例外,你别无选择;必须在方法的throws
子句中声明异常。
答案 3 :(得分:1)
试试这个..
调用 fillInStackTrace()
方法在新创建的throwable中重新初始化堆栈跟踪数据。在尝试访问API时,屏蔽有关异常的信息将会有所帮助。
答案 4 :(得分:1)
原样,最好选中/取消选中自己的异常。但在此之前,尽可能尝试修复底层异常。我总是喜欢以下方式,
try {
// JDBC code
}
catch (SQLException e) {
// try to solve the exception at API level
bollean solvable = trySolveException(e);
if (!solvable) {
// Alert the admin, or log the error statement for further debugging.
mailClient.sendMailToDBAdmin("Some issue storing password", e);
// or
LOG.severe("some issue in storing password " + e.toString);
throw MyException("A request/logstatement is logged on your behalf regarding the exception", e);
}
LOG.info("The exception is solved");
}
finally {
// don't forget to free your resources - to avoid garbage and memory leaks, incase you have solved the issue in trySolveException(e).
}
所以,
1)您没有直接公开SRQException,但是您抛出了自己的异常版本。
2)你试图解决一次异常,如果不是,你通过邮件或日志声明以某种方式提醒。
3)最后,如果您成功解决了异常,就已经释放了所有资源。
如果使用新的Java7 try with resource close选项,则可以避免使用finally子句。
对于是否抛出已检查或未经检查的异常,我将举例说明
1)说出像NPE这样的例外 - 它们是编程错误,开发人员应该更负责没有创建NullPointer。您不希望您的代码考虑到这种粗心错误并尝试(NPE),catch(NPE)。因此抛出未经检查的异常。
2)另一方面,SQL异常等异常在极少数情况下会占一些外部依赖性。因此,最好抛出用户定义的已检查异常。并且用户可以确定他是否可以连接到备份SQL服务器(如果有的话)。
3)还有另一个例外条款,其中程序无法继续。说出一个没有界限的记忆。它们应该被抛出为错误。