3

我有一个返回字符串的getter,我将它与其他字符串进行比较。我检查 null 的返回值,所以我的if语句看起来像这样(如果它是真的,我真的会提前退出)

if (someObject.getFoo() != null && someObject.getFoo().equals(someOtherString)) {
  return;
}

在性能方面,存储返回的字符串会比像这样调用两次 getter 更好吗?这还重要吗?

String foo = someObject.getFoo();
if (foo != null && foo.equals(someOtherString)) {
  return;
}

为了回答评论中的问题,这种检查并不经常执行,而且 getter 相当简单。我很好奇分配一个新的局部变量与再执行一次 getter 相比如何。

4

5 回答 5

11

这完全取决于吸气剂的作用。如果它是一个简单的 getter(检索数据成员),那么如果 JVM 确定代码是性能的热点,它将能够即时内联它。这实际上就是为什么 Oracle/Sun 的 JVM 被称为“HotSpot”的原因。:-) 它会在它认为需要的地方(如果可以的话)应用积极的 JIT 优化。但是,如果 getter 做了一些复杂的事情,使用它并让它重复该工作自然会更慢。

如果代码不是热点,当然,您不在乎是否存在性能差异。

有人曾经告诉我,内联的 getter 有时可能比缓存到局部变量的值更快,但我从未向自己证明过这一点,也不知道为什么会这样。

于 2013-01-23T17:51:45.033 回答
4

使用第二块。无论如何,第一个块很可能会优化到第二个块,而第二个块更具可读性。 但主要原因是,如果 someObject 曾经被其他线程访问过,并且如果优化以某种方式被禁用,第一个块将不会抛出 NullPointerException 异常。

另外:即使没有多线程,如果 someObject 有任何机会变成volatile,优化也会消失。(对性能不利,当然,多线程也糟糕。)最后,第二个块将使调试器的使用更容易(这不是必需的。)

于 2013-01-23T19:12:15.730 回答
1

您可以省略第一个 null 检查,因为 equals 会为您执行此操作:

当且仅当参数不为 null 并且是表示与此对象相同的字符序列的 String 对象时,结果才为真。

所以最好的解决方案很简单:

if(someOtherString.equals(someObject.getFoo())
于 2013-01-23T22:31:10.487 回答
0

它们看起来都一样,即使在性能方面也是如此。如果您确定不会进一步使用返回值,请使用第一个块,如果没有,请使用第二个块。

于 2013-01-23T17:55:09.163 回答
0

我更喜欢第二个代码块,因为它分配了 foo,然后 foo 不能更改为 null/notnull。

Null 通常是必需的,Java 应该使用“Elvis”运算符来解决这个问题:

if (someObject.getFoo()?.equals(someOtherString)) {
  return;
}
于 2013-01-24T06:34:09.080 回答