有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在从getter返回之前检查null是一种不好的做法吗?

我想防止getter返回空值,比如下面的示例。这种做法不好吗

例1

public Integer getMinutes() {
   if (minutes == null)
       minutes = 0;
   return minutes;
}

例2

public List getTasks() {
   if (tasks == null)
       tasks = new ArrayList();
   return tasks;
}

共 (2) 个答案

  1. # 1 楼答案

    简单的回答是:这取决于

    更具体地说,在没有看到整个课堂并理解其设计的情况下,这个问题不可能以一般的方式回答。空检查是一个实现细节,在某些设计中是合适的,但在其他设计中可能是一种气味

    一般来说,方法必须遵守它们的契约,仅此而已。因此,从API设计的角度来看,这个问题无关紧要。您可以按照一长串现有的最佳实践来设计API,然后根据需要设计实现。其中一个最佳设计实践是,在返回Collection时,不应将“零元素”特例化为null。也就是说,如果你的方法可以合理地返回一个空集合,它应该返回一个空集合,而不是像null这样的特殊值。这几乎总是简化了客户端代码,并删除了一整类潜在的NPE。这并不意味着您不能在内部使用null来标记“零元素”,但这意味着如果您这样做,您应该在返回时执行转换(如示例中所示)

    因此,如果getTasks()方法指定它总是返回一个(可能是空的)列表,那么在示例中使用空检查是一个合理的实现选择。在您的具体示例中,它可能不是最佳选择,因为JDK提供了Collections.emptyList<T>()之类的方法,它允许您以低廉的成本重新使用单例空列表实例,因此您不会在内存中保存任何内容,而且CPU的节省值得怀疑

    此外,通过使用“null表示空列表”约定,您要求所有内部方法要么必须检查tasks == null,要么使用gettask()方法。在集合对象的特定案例中,我通常更喜欢使用Collections.empty*方法而不是null来表示空列表2。类似的推理适用于Integer情况,因为Integer.valueOf(0)all compliant JVMs上返回一个单例对象

    撇开这些具体情况不谈,当然有理由使用空检查来表示缺少的或默认的元素,尤其是在没有好的“空”元素出现或性能很重要的情况下。您会发现这种模式在设计良好的库(如Java运行时和Guava)中使用得比较频繁。所以你不能说这是个坏习惯。这是一种需要仔细评估的实践


    1这些Collection.empty*方法的使用也适用于您的示例。在空的情况下,可以考虑直接返回^ {CD13}},而不是按需创建新的^ {< CD14}}。这是否合适取决于整个类设计,例如,该列表是否可变

    2是否Collections.emptyList()比显式空检查快实际上是一个复杂的问题。如果空列表非常罕见,以至于它们通常不会在给定的过程中出现,那么emptyList()方法可能会更快,因为随着空列表的频率变为零,它的成本(获取者wrt)也会变为零。另一方面,当空列表出现时,它可能会为所有使用List的方法创建一个多态调用站点:每个这样的站点可能会看到一个特殊的“空列表”实现和ArrayList。这可能会降低代码的速度,尽管这在很大程度上取决于内联决策。因此,与通常的性能考虑一样,确切的答案是复杂的,如果细节重要,您需要分析

  2. # 2 楼答案

    一般来说,是的,这是不好的做法

    例如1,如果对象的值(在本例中是一个整数)真的是null,那么API用户会期望返回null。不是0。例如,您的API的用户可能将0视为花费0分钟的操作,而null可能被解释为意味着从未发生过任何事情。)

    例如,API用户不会期望getter产生这样的副作用,比如构建一个新列表

    除非在方法的契约(javadoc)中包含这些行为,否则用户无法意识到实际发生了什么,这可能会导致他们使用不正确的数据。相反,他们应该预测null可以来自这些方法,并自行检查

    但是,您可以通过使用javax.annotation.Nullablejavax.annotation.Nonnull等注释来帮助用户(及其ide),分别提示返回值可以为null,也不能为null。通过这种方式,他们可以智能地预测并响应方法结果的无效能力

    警告:正如罗伯特在回答中所说,在某些情况下,延迟加载是有意义的。但必须谨慎行事,而且只能在有意义的情况下进行。Joshua Bloch在他的书《有效的Java,第二版》中写了一个关于惰性初始化的子章节,他在书中解释说,惰性初始化应该“明智地”执行,并有效地称之为预优化