Java:使用getter vs缓存值

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

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

从表面上看,存储返回的String而不是像这样两次调用getter会更好吗? 它甚至重要吗?

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

要回答评论中的问题,不会经常执行此检查,并且getter非常简单。 我很好奇如何分配一个新的局部变量与另外一次执行getter相比。

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

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

有人曾告诉我,内联的getter有时会比缓存到局部变量的值更快,但我从来没有向自己certificate这一点,也不知道为什么会出现这种情况的理论。

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

另外:即使没有multithreading,如果someObject任何机会变得不稳定 ,优化也会消失。 (对于性能不好,当然,对于多个线程来说真的很糟糕。)最后,第二个块将使调试器变得更容易(不是那种必要的。)

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

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

所以最好的解决方案就是:

 if(someOtherString.equals(someObject.getFoo()) 

它们看起来都相同,甚至是性能明智。如果您确定不会再使用返回值,请使用第1个块,如果不是,请使用第2个块。

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

通常需要Null,Java应该使用’Elvis’运算符来解决这个问题:

 if (someObject.getFoo()?.equals(someOtherString)) { return; }