多次调用getter或调用一次并分配给变量?

假设我有class级:

public class Age { private int age; public int getAge() { return this.age; } } 

在我的Main类中,我多次调用getAge()方法。

所以我想知道调用这么多次或调用一次并将其分配给某个变量并使用该变量是明智的。

哪个最好,为什么?

这可能是您在知道需要之前进行优化的情况。 该值只是一个整数,因此如果将值存储在多个位置,它不会占用大量内存。 同时,这是一个非常简单的方法调用,不会花费太多时间来执行。 以您认为最具可读性的方式编写它。 然后,在拥有可靠版本的代码之后,您可以使用分析工具来查看是否存在明显的差异。

不要尝试对此进行微观优化,除非您在分析时发现它确实是一个瓶颈。 我使用getAge()访问器方法,因为它很可能是最易维护和最明显的解决方案。

话虽这么说,这两种方法可能会完全相同。 在运行时,JIT很可能完全优化掉getAge()调用,因此在两种情况下都是单一的基本访问。

多次调用getAge()方法可能会有一些性能开销,但我建议你考虑微优化剧院的悲剧悲剧 。

这是您作为API编写者必须向调用者指示的内容。

通常,如果您只是返回一个属性,则可以将该调用标记为final(如果您没有提供实际的接口)。 这应该可以降低调用的成本,因为编译器更有可能内联函数。

如果计算属性的成本很高(例如,字符串查找),请在JAvaDocs中为该方法记录它,并向调用者指示他们可能想要获取该值一次并将其缓存。

不要打扰。 像这样绝对不值得微优化。 等到你完成代码,然后运行得太慢,然后拿出一个分析器,然后研究分析器告诉你的问题的根源。

过早优化是万恶之源。

根据应用程序的设计方式,这两个选项实际上可能会产生不同的结果! 如果您使用的年龄实例是共享且可变的,则应用程序中的不同位置可能会在您调用getAge()之间更改其值。 在这种情况下,确定哪个是您的代码的最佳选项是正确的问题,由您决定。 正如古老的谚语所说:“首先使它正确,然后快速”。 并且,正如其他人已经提到的那样,在这种情况下,您可能不需要担心“快速”。

一个相关的例子是当你在迭代它时更改一个集合。 您必须迭代快照以不获取ConcurrentModificationException

我将尝试用代码示例说出其他答案已经说过的内容。

在你提出getAge()的调用非常简单的情况下,调用它的成本几乎为零。 在这种情况下不要打扰它。

但是,如果你的getAge是一些花哨的东西,可以进行大量计算或访问IO资源,例如:

 public int getAge() { return slowService.calculateAgeByBirthDate(birthDate); // it takes 2 seconds to execute for every call } 

那么肯定是缓存de result并使用它是个好主意。 因为如果你打电话30次,你的代码需要1分钟才能完成。

我认为你会发现在运行时没有区别 – 假设你没有创建多个Age类。

对于像这样的简单情况,我会选择看起来最好的代码。

在某些情况下,建议您调用一次并读取保存的返回值,例如

 for (int i = 0; i < list.size(); i++) doSomethingThatDoesNotAffectSizeOfList(); 

因为编译器可能无法确定循环体是否影响列表的大小。 正确实现的列表应该始终能够轻松地告诉它的大小,但在其他示例中(或者在处理实现不佳的集合时),它可能会更糟。

通常,如果方法计算量很大,则可以使用memoization ,这基本上意味着您缓存已计算的输入/输出值。

记忆function“记住”与某些特定输入相对应的结果。 使用记忆输入的后续调用将返回记住的结果而不是重新计算结果,从而消除了除了使用这些参数对函数进行的第一次调用之外的所有参数的调用的主要成本。

这种技术将“为效率保存 - 返回 - 价值”推入方法本身,这简化了维护bla bla bla ...

棘手的部分是理解现代JVM在根据运行时可用的知识编译字节代码时进行积极的优化。

例如,如果给定方法未在子类中重写,则可以将其视为与final方法完全相同,允许JVM在调用方法中内联其代码的副本,而不是显式执行方法调用。 (如果条件发生变化,那么这些类将被简单地视为新类,因此稍后会根据新条件重新编译)。

这意味着为bean attibutes获取/设置(其中值只是存储和检索,而不是计算)非常便宜,您应该每次都进行调用并期望JVM检测可能的优化并应用它们。

除非您在getAge()方法中执行许多操作,否则您将看不到性能上的太大变化。

在这种情况下,我建议不要考虑性能,看看可用性和代码重用。 您当前的实现是最简单的getter,它返回一个整数。

但是,如果某个地方存储了一个人的生日并希望动态生成年龄呢? 如果您只是直接调用该属性,则会被迫重构您的代码。 但是,改变getAge()的内部结构,你可以把计算放在那里,然后就完成了。

我真的很喜欢编程语言来引入一个’超私有’属性/字段修饰符,基本上说’你只能通过它的访问者访问这个属性’。