Java—应该在何处以及如何使用异常?
我读了一些关于Java中异常处理的内容,以便能够编写更好的代码。好吧,我承认,我有罪;我使用了太多的try-catch{}块,在catch中使用了Java—应该在何处以及如何使用异常?,java,exception,exception-handling,Java,Exception,Exception Handling,我读了一些关于Java中异常处理的内容,以便能够编写更好的代码。好吧,我承认,我有罪;我使用了太多的try-catch{}块,在catch中使用了ex.printStackTrace(),甚至没有使用正确的记录器(实际上System.out和System.err被重定向到PrintWriter,因此生成了日志)。然而,经过几个小时的阅读,我发现自己在一个陌生的地方:未知。如果异常被设计为传递有关异常流状态的信息,那么如何知道在哪里使用该信息进行操作 例如,当发生数据库错误时,应该返回空值或错误代
ex.printStackTrace()
,甚至没有使用正确的记录器(实际上System.out
和System.err
被重定向到PrintWriter
,因此生成了日志)。然而,经过几个小时的阅读,我发现自己在一个陌生的地方:未知。如果异常被设计为传递有关异常流状态的信息,那么如何知道在哪里使用该信息进行操作
例如,当发生数据库错误时,应该返回空值或错误代码,还是引发异常?如果抛出,那么应该在哪里处理该异常?我明白,如果你对此无能为力,即使记录一个异常也是没有用的。但是,在GUI应用程序中,这可能很容易杀死您的GUI(我正在使用SWT,而且我经常看到这种情况),即使是menuShown()
方法(如果不处理ArrayIndexOutOfBounds
异常,将关闭应用程序)。这个例子可能会一直持续下去,但下面是问题的总结:
坦率地说,在2-3年的时间里,我只听说过并使用了我认为只有10%的Java标准异常。是的,有人说如果调用方不知道如何处理抛出的异常,他就无权调用抛出方法。是这样吗
我知道这个主题是永恒的,但实际上我期待着用你的建议来回顾一个150个班级的中等规模项目。非常感谢。我们在团队中做的一件事就是为我们的错误设置自定义异常。我们使用的是Hibernate验证器框架,但您可以在任何框架或股票例外情况下执行此操作 例如,我们有一个ValidationException来处理验证错误。我们有一个ApplicationException来处理系统错误 您确实希望尽量减少尝试捕捉的次数。在我们的例子中,我们将让验证器收集“InvalidValue”对象中的所有验证,然后抛出一个ValidationException,其中绑定了无效值信息。然后您可以向用户报告哪些字段出错,等等 在您提到的数据库错误的情况下,您可能不想将stacktrace发送到UI(最好记录)。在这种情况下,您可以捕获数据库异常,然后将自己的ApplicationException抛出到GUI中。您的GUI不必知道如何处理无限多的服务器错误,但可以设置为处理更普遍的ApplicationException—可能报告服务器有问题,并指示用户应联系您的客户支持部门报告问题
最后,由于所依赖的外部API,有时您会情不自禁地使用大量try/catch块。这很好。如前所述,捕获外部异常,并将其格式化为对应用程序更有意义的异常。然后抛出自定义异常。对于异常,一般的经验法则是,如果你能做些什么,捕获它并处理它,如果你不能,重新抛出到下一个方法。要了解您的一些具体情况:
try {
// some database operation
}
catch (IOException ex) {
// retry the database operation. then if an IO exception occurs rethrow it. this shows an example doing something other than just catch, logging and/or rethrowing.
}
如果你愿意的话,我很乐意详细介绍其中的任何部分
for (int retries = 0;; retries++) {
try {
commandService.execute(command);
return;
} catch (Exception e}
Log.error(e);
if (retries < 3) {
continue;
} else {
saveForAnalysis(command, e);
alertOperator();
return;
}
}
}
interface DBAccess {
public Result accessDB();
}
class DBOperation {
static public void DoOperation(DBAccess pAccess) {
try { return DBAccess.accessDB(); }
catch(InvalidDBPasswordException IPE) {
// Do anything about invalid password
}
catch(DBConnectionLostException DBCLE) {
// Do anything about database connection lost
}
// Catch all possible DB problem
}
}
...
private User[] ShowUserList_and_ReturnUsers() {
// Find the used.
// Show user list
if (Users.count() == 0)
return null;
else return Users;
// No need to handle DB connection problem here
}
private User[] GetUserProfile() {
// Find the used and return
// No need to handle DB connection problem here
}
...
/** An onClick event to show user list */ {
DBOperation.DoOperation(new DBAccess() {
public Result accessDB() {
return ShowUserList_and_ReturnUsers();
}
});
}
/** An onClick event to show a user profile */ {
DBOperation.DoOperation(new DBAccess() {
public Result accessDB() {
return GetUserProfile();
}
});
}
... Many more DB access
for(int i = 0; i < Users.length; i++) {
User aUser = Users[i];
// Do something with user
}
Replaced with
try {
for(int i = 0; ; i++) {
User aUser = Users[i];
// Do something with user
}
}
catch(ArrayOutOfBoundException AOBE) {}