10

如果参数存在于数据库中,我有一个返回 id 号的函数。如果不是,则返回 null。这是在乞求空指针异常吗?不允许使用负 id 编号,但我认为让不存在的参数返回 null 而不是像 -1 这样的错误代码会更清楚。你怎么看?

private Integer tidOfTerm(String name) throws SQLException {
    String sql = "SELECT tid FROM term_data WHERE name = ?";
    PreparedStatement prep = conn.prepareStatement(sql);
    prep.setString(1, name);
    ResultSet result = prep.getResultSet();

    if (result.next()) {
        return result.getInt("tid");
    }

    return null; // TODO: is this begging for a null pointer exception?
}
4

14 回答 14

16

这是完全合法的。如果要避免 NPE,请抛出自定义异常。但不要返回负数。如果调用者不检查返回值,你总会遇到问题。但是进行错误计算(因为结果例如乘以 -1)肯定比未捕获的异常更难调试。

于 2010-01-24T19:44:26.440 回答
3

null在不给出结果的查找的情况下返回 a是表示不存在的正常方法。在这种情况下,我会选择它。(标准 Java Map 类的查找方法是null在地图不包含键的情况下使用的示例。)

至于为 ID 返回一个特殊值,我只建议在您的系统已经包含表示特殊 ID 的特殊值时这样做。

另一个经常听到的可能性是在这种情况下抛出异常。然而,使用异常来传递状态是不明智的,所以我也不会这样做。

于 2010-01-24T19:47:43.910 回答
2

我认为在这种情况下返回 null 是合法的。只需确保正确记录意图即可。

在这种情况下返回负值是可以的,但这不是一个全面的解决方案。如果数据库中允许负值怎么办?

编辑:我想添加一个关于 SO 关于返回空值或空列表(或数组)的相关讨论的内容。我赞成返回空列表或数组而不是 null,但上下文不同。当试图获取一个列表时,它通常是父对象的一部分,并且父对象有一个空列表而不是空引用实际上是有意义的。在这种情况下,null 有一个含义(= 未找到),没有理由避免返回它。

于 2010-01-24T19:31:49.577 回答
1
  • 不要使用错误代码!哪个值是错误?它永远不会成为合法的返回值吗?什么都没赢。

  • 空是不好的。大多数调用者代码必须对结果进行 if not null 检查。有时选择可能会返回 null。它应该与没有行不同吗?

  • 抛出 NoSuchElementException 之类的异常,而不是返回 null。这是一个未经检查的异常,调用者可以处理它或传递它。如果调用者想要处理,try catch 并不比 if not null 复杂。

于 2010-01-24T20:25:47.357 回答
1

我希望这对你来说不是一个真正的方法。您没有在方法范围内关闭 Statement 或 ResultSet。

于 2010-01-24T19:32:44.403 回答
1

我建议你考虑选项模式。

选项模式充当您返回类型的包装器,并定义了两种特殊情况:option.none() 和 option.some()。这样,您始终知道返回的类型(选项),并且可以使用 option.isSome() 和 option.isNone() 等方法检查返回的 Option 对象中是否有值。

这样,您可以保证没有任何未经检查的空值。

当然,所有这些都是以增加代码复杂性为代价的。

有关选项类型的更多信息,请参见此处(Scala 代码,但主体相同)

于 2010-01-24T21:52:31.080 回答
0

这可能会给新手用户带来很大的麻烦。优秀的编码人员会认识到,如果名称无效,则null可能会被退回。话虽如此,更标准的事情是扔一些exception

于 2010-01-24T19:46:49.027 回答
0

我想说最好的解决方案取决于您的方法的名称,您应该考虑您的方法的名称,以及它们是否应该返回 null 或抛出异常。

tidOfTerm对我来说暗示 Term 应该存在,所以发现一个不存在应该抛出一个异常。

如果术语名称在您自己的代码的控制之下,并且找不到它表明您的代码或环境中存在错误,那么您可能需要抛出 IllegalArgumentException。

如果术语名称参数不受您的控制,并且找不到有效术语是一种完全有效的情况,那么我会将您的方法重命名findTidForTermName为稍微暗示将要执行某种搜索,并且因此,搜索可能找不到任何东西。

于 2010-01-24T22:40:55.193 回答
0

结合自动装箱可能会很棘手。如果我这样做:

final int tid = tidForTerm("term");

并且“术语”不存在,我将得到一个 NPE,因为 Java 试图将整数(null)拆箱为原始 int。

然而,在某些情况下,对整数使用 null 实际上是件好事。在具有可选 int 值的实体中,例如城市的人口。在这种情况下, null 意味着没有可用的信息。

于 2010-01-24T20:17:09.193 回答
0

一个有趣的问题和大量可能的解决方案:

  1. 创建一个 HasArgument 方法并要求用户调用它,问题这可能很慢并且重复工作
  2. 如果值不在数据库中,则抛出异常,仅应在意外情况下使用
  3. 使用附加值来指示无效返回,null 和负值对您有用,但如果不检查它们可能会导致代码稍后出现问题。
  4. 返回带有 isValid() 和 getValue() 方法的包装器,其中 getValue() 在无效时抛出异常。这将解决 1 和 3 的问题,但可能有点过于含糊。
于 2010-01-24T21:34:20.710 回答
0

不,不会的。如果您事后对其进行操作,它只会抛出 NPE,就好像它是一个原语而不检查它一样。比如i++等等。您的示例是有效的(期望 JDBC 代码本身正在泄漏资源)。如果您不需要实际的id,那么另一方面,您也可以只返回 a boolean

于 2010-01-24T19:29:07.010 回答
-3

是的,它应该导致 NPE,是的,您应该在调用方法(或其他合适的地方)中捕获它。您的方法返回 NULL 的最可能原因是当没有记录时,正确的处理方法是抛出异常。告诉某人你没有他要求的东西的完美例外是 NPE。

返回错误代码(例如 -1)不好,因为:

a) 如果您要处理许多错误(例如,无法读取 DB、可以读取 DB 但 DB 中不存在对象、找到对象但某些内容已损坏等),则返回错误代码不会区分类型错误。

b) 将来如果 -1 成为合法术语 id,那么将很难更改它(如果您必须使用 -1,那么(编辑:在 C 中)至少执行 #define ERRORCODE -1 并在任何地方使用 ERRORCODE)

于 2010-01-24T19:42:09.273 回答
-3

请不要编写返回 null 的代码。这意味着对您的代码的每次调用都必须检查 null 以保持健壮。每次。总是。

考虑返回一个列表,而不是包含可能为零的返回值的数量。

于 2010-01-24T20:17:45.260 回答
-3

我同意海报。Integer 是一个包装器,因此应该用于计算、转换等(我认为您打算这样做)。不要返回空值,使用负数......它更优雅一些,让您可以进行更多控制。恕我直言。

于 2010-01-24T19:33:31.673 回答