【问题标题】:Is there a cost associated with frequent object attribute access?频繁访问对象属性是否会产生成本?
【发布时间】:2020-04-19 08:28:06
【问题描述】:

我在编写代码时主要遵循的一件事是,如果我看到某个对象属性或方法在同一个方法中被多次访问,我倾向于将它分配给一个变量并在任何地方重复使用它。

List<ItemA> itemAList = alpha.doX(..., ..., ...)
              .peek(item -> packagedItems.put(item.getName(), ...))
              .peek(item -> readyItems.put(item.getName(), ..., ...)))
              .map(item -> transform(item.getName(), ...))
              .collect(toList());

正如我们所见,item.getName() 已被多次使用。我通常会将它移动到一个变量中并重新使用它:

String itemName = item.getName();
List<ItemA> itemAList = alpha.doX(..., ..., ...)
              .peek(item -> packagedItems.put(itemName, ...))
              .peek(item -> readyItems.put(itemName, ..., ...)))
              .map(item -> transform(itemName, ...))
              .collect(toList());

我有时也会在代码审查中提出相同的建议。但是,我想现在是否有任何性能成本必须从对象实例中取消引用而不是直接能够从变量访问?

围绕这种做法有哪些想法?在什么情况下(如果有的话)一个会比另一个更受欢迎?

谢谢。

【问题讨论】:

  • 您发布的两个代码 sn-p 具有不同的语义。事实上,第二个版本甚至不应该编译,说明变量item 已经被定义。即使要编译 item -&gt; ...(item.getName)... 也是一个 lambda 函数,因此不等同于 item -&gt; ...(itemName)...。

标签: java code-formatting code-readability


【解决方案1】:

(忽略第二个代码中的错误,item 已在使用中。)

当方法为final 时,编译器可能会内联,因为由编译器决定该方法是否足够“简单”以进行内联。 getter 和 setter 通常很简单,可以内联。

如果不是,JIT 很可能迟早会在​​运行时内联 getter,因此item.getName() 将被item.name 替换

没有太大的性能问题。

【讨论】:

  • 不应依赖 JIT 内联方法。如果 getter 不经常被调用,它就不会被内联。 (值得注意的是,当一种方法被认为是“热”时,您可以配置阈值)。此外,如果一个类有任何继承自它的类,则其非 final 方法不适合内联。
猜你喜欢
  • 2016-05-10
  • 2016-11-27
  • 2016-05-03
  • 2014-09-25
  • 2012-01-21
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多