我刚开始开发 Android 应用程序,令我感到非常惊讶的是,像 android.database.DatabaseUtils 这样的 API 在使用其方法时不会向上抛出异常。我想知道我认为糟糕的设计的原因是什么。 (一定是有原因的。。)
例如here
使用方法long execute()
public long execute() {
if (mPreparedStatement == null) {
throw new IllegalStateException("you must prepare this inserter before calling "+ "execute");
}
try {
if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
return mPreparedStatement.executeInsert();
} catch (SQLException e) {
Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
return -1;
} finally {
// you can only call this once per prepare
mPreparedStatement = null;
}
}
所以这个方法正在捕获 SQLException,而不是向调用者抛出这个或另一个包装的异常,它只是返回 -1 并使用 logcat 记录错误。
作为一名开发人员,我发现这非常令人震惊,就好像我正在使用这个 API 并且我得到一个值 -1 我知道出了点问题,但我不知道为什么出了问题,除非我检查 logcat 日志。
也许我弄错了,请让我知道,但是一个 API 的方法返回 -1 的操作是一个糟糕的 OO 设计,如果出现问题它可以简单地抛出异常并让开发人员以他/她希望从 Exception 对象中提取所有详细信息的方式处理该异常。你不觉得吗?
有什么理由这样做吗?
我已经将 logback 与我的应用程序集成在一起,我希望不需要为任何事情使用 logcat。但是在看到这个 API 之后,我担心我将不得不以某种方式将过滤后的 logcat 导出到一个文件中,以查看当我的应用程序收到 -1 在 SQLlite 上执行某些操作时出了什么问题。
有什么建议吗?我在这里遗漏了什么吗?
非常感谢!
最佳答案
首先,我们不是最初编写代码的 Google 工程师,也不是介意读者。我们不能确定为什么一段代码是这样设计的。但我们可以做出有根据的猜测。请考虑以下事项:
数据库 API 建立在 sqlite3 C 库之上。 C 没有异常,异常错误条件通过其他方式发出信号,例如返回一个特殊值,例如 -1。
从设计的角度来看,
android.database
包中的 API 抛出异常android.database.sqlite
包会暴露不必要的实现细节。 (尽管还有其他方法通过使用SQL*
类来公开此类细节。) 如您所述,将详细的异常包装在 API 级异常中会更好。“Utils”类通常不是真正设计的。它们只是开发人员发现经常需要的方法的集合。您不必使用它们。
异常处理在性能方面相对昂贵。返回特殊值要便宜得多。避免异常可能是一个好主意,尤其是在经常执行的低级代码中。虽然这一点与您链接的代码无关,因为它包含一个
try
-catch
block 。总的来说,Android sqlite API 的设计并不是特别典型。我之前写过它的一些奇怪之处,例如 here .
关于java - 为什么android.database.DatabaseUtils不会抛出SQLException等异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24729463/