多次调用 getter 还是调用一次并分配给变量?
假设我的类为:
public class Age {
private int age;
public int getAge() {
return this.age;
}
}
在我的主类中,我多次调用 getAge() 方法。
所以我想知道是否建议多次调用或调用一次并将其分配给某个变量并使用该变量。
哪个最好,为什么?
say suppose I have class as :
public class Age {
private int age;
public int getAge() {
return this.age;
}
}
In my Main class I am calling the getAge()
method many times.
So I wanted to know is it advisable to call so many times or call once and assign it to some variable and use that variable.
Which is best and why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
这可能是您在知道需要之前进行优化的情况。该值只是一个整数,因此如果将该值存储在多个位置,它不会占用大量内存。同时,它是一个非常简单的方法调用,不会花费太多时间来执行。以您认为最易读的方式编写。然后,在获得可靠的代码版本后,您可以使用分析工具来查看是否存在明显的差异。
This is likely a situation where you are optimizing before you know you need to. The value is just an integer so it is not taking up a lot of memory if you store the value in multiple places. At the same time, it is a very simple method call that will not take much time to execute. Write it in a way that you feel is most readable. Then after you have a solid version of the code, you can use a profiling tool to see if there is a noticeable difference.
不要尝试对此进行微观优化,除非您发现它确实是分析时的瓶颈。我会使用 getAge() 访问器方法,因为它很可能是最可维护和最明显的解决方案。
话虽这么说,这两种方法的效果可能完全相同。在运行时,JIT 很可能会完全优化 getAge() 调用,因此在这两种情况下它都将是单个原始访问。
Don't try to micro-optimize this, unless you find that it's truly a bottleneck while profiling. I'd use the getAge() accessor method, since it's most likely the most maintainable and obvious solution.
That being said, the two approaches are likely to perform exactly the same. At runtime, the JIT will most likely optimize away the getAge() call entirely, so it will be a single primitive access in both cases.
多次调用
getAge()
方法可能会产生一些性能开销,但我建议您考虑 微优化剧院的悲伤悲剧。There may be some performance overhead of calling the
getAge()
method many many times, but I suggest you consider The Sad Tragedy of Micro-Optimization Theater.作为 API 编写者,您必须向调用者表明这一点。
一般来说,如果您只是返回一个属性,则可以将调用标记为最终调用(如果您不提供实际的接口)。这应该会降低调用成本,因为编译器更有可能内联该函数。
如果计算属性的成本很高(例如,字符串查找),请将其记录在该方法的 JAvaDocs 中,并向调用者表明他们可能希望获取该值一次并将其缓存。
This is something that you, as the API writer, have to indicate to the caller.
In general, if you are simply returning a property, you can mark the call as a final (if you are not offering an actual interface). That should reduce the costs of calls since the compiler would be more likely to inline the function.
If the cost of calculating the property is expensive (E.g., a string lookup), document it in the JAvaDocs for that method, and indicate to the caller that they may want to obtain the value once and cache it.
别打扰。这样的微优化绝对不值得。等到您完成代码,然后它运行得太慢,然后拿出分析器并根据分析器告诉您的问题根源进行处理。
过早的优化是万恶之源。
Don't bother. It's absolutely not worth micro-optimizing like this. Wait until you finish your code, then it runs too slowly, then get out a profiler and work on what the profiler tells you is the source of the problem.
Premature optimization is the root of all evil.
根据您的应用程序的设计方式,这两个选项实际上可能会产生不同的结果!如果您使用的年龄实例是共享且可变的,则应用程序中的不同位置可能会在调用
getAge()
之间更改其值。在这种情况下,决定哪个是最适合您的代码的正确性问题取决于您的决定。正如古老的格言所说:“先做对,然后做快”。而且,正如其他人已经提到的,在这种情况下,您可能不需要担心“使其快速”部分。一个相关的示例是当您在迭代集合时更改集合时。您必须迭代快照才能避免出现 ConcurrentModificationException。
Depending on how your application is designed, the two options might actually give different results! If the age instance you're using is shared and mutable, different places in your application might change its value in between your calls to
getAge()
. In this case, it's a matter of correctness to decide which is the best option for your code, and it's up to you to decide. As the old adage says: "first make it right, then make it fast". And, as others have already mentioned, you probably won't need to worry about the "make it fast" part in this case.A related example is when you're changing a collection while iterating through it. You have to iterate over a snapshot to not get a
ConcurrentModificationException
.我将尝试用代码示例来说明其他答案已经说过的内容。
在您提出的情况下,对 getAge() 的调用非常非常简单,并且调用它的成本几乎为零。在这种情况下,不要理会它。
但是,如果您的 getAge 是一些奇特的东西,需要进行大量计算或访问 IO 资源,例如:
那么缓存结果并使用它肯定是个好主意。因为如果您调用它 30 次,您的代码将需要 1 分钟才能完成。
I'll try to say with code examples what the other answer already said.
In the case you presented the call for getAge() is very very simple, and the cost of calling it is almost nothing. Don't bother with it in this case.
But if your getAge was something fancy that do lots of calculations or access IO resources, like:
Then for sure it would be a good idea to cache de result and use it. Because if you call it 30 times your code will take 1 minute to complete.
我认为您在运行时不会看到任何差异 - 假设您不创建多个 Age 类。
i think you will see no difference at runtime - assuming you do not create more than one Age class.
对于像这样的简单情况,我会选择代码看起来最好的一个。
在某些情况下,建议调用一次并读取保存的返回值,例如,因为
编译器可能无法确定循环体是否影响列表的大小。一个正确实现的列表应该总是能够轻松地知道它的大小,但在其他示例中(或在处理实现不佳的集合时),情况可能会更糟。
一般来说,如果一个方法计算量很大,你可以使用 memoization,这基本上意味着你缓存已经计算的输入/输出值。
这种技术将“节省返回值以提高效率”推入方法本身,从而简化了维护等等......
For a simple case like this, I'd go for the one that looks best code-wise.
There are a few cases where it is advisable to call once and read the saved return value, such as in
since the compiler may have trouble figuring out if the body of the loop affects the size of the list. A properly implemented list should always be able to tell it's size easily, but in other examples (or when dealing with poorly implemented collections) it might be worse.
In general, if a method is computationally heavy, you could use memoization, which basically means that you cache already computed input / output values.
This technique pushes the "save-the-return-value-for-efficiency" into the method itself, which eases the maintenance bla bla bla...
棘手的部分是了解现代 JVM 在根据运行时可用的知识编译字节码时会进行积极的优化。
例如,如果给定方法没有在子类中被重写,则可以将其视为与最终方法完全相同,从而允许 JVM 在调用方法中内联其代码的副本,而不是显式执行方法调用。 (如果条件发生变化,这些类将被简单地视为新类,因此稍后会根据新条件重新编译)。
这意味着 bean 属性的获取/设置(其中的值只是存储和检索,而不是计算)非常便宜,您应该每次都进行调用,并期望 JVM 检测可能的优化并应用它们。
The tricky part is understanding that modern JVM's do aggressive optimizations when compiling byte code based on the knowledge available at runtime.
If, for instance, a given method is not overridden in a subclass it can be treated exactly the same as a final method, allowing the JVM to inline a copy of its code in the calling method instead of explicitly doing a method call. (If conditions change, those classes are then simply considered new and hence recompiled later based on the new conditions).
This means that get/set for bean attibutes (where the values are simply stored and retreived, and not calculated) are very cheap and you should do the calls everytime and expect the JVM to detect the possible optimizations and apply them.
除非您在 getAge() 方法内执行许多操作,否则您不会看到性能有太大变化。
You won't see much change in performance unless if you are doing many operations inside the getAge() method.
在这种情况下,我建议不要考虑性能,而应该考虑可用性和代码重用。您当前的实现是最简单的 getter,它返回一个整数。
但是,如果您存储一个人的生日并想要动态生成年龄怎么办?如果您只是直接调用该属性,那么您将被迫重构代码。但是,通过改变 getAge() 的内部结构,您可以将计算放入其中,然后就完成了。
我真的很希望编程语言引入一种“超私有”属性/字段修饰符,基本上是说“您只能通过其访问器访问该属性”。
In this case, I'd suggest don't look at performance, look at usability and code reuse. Your current implementation is the simplest of getters, one that returns an integer.
But what if somewhere down the line you store a person's birthdate and want to dynamically generate the age? If you simply call the property directly, you then are forced to refactor your code. However, altering getAge()'s internals, you can put the calculation in there, and you're done.
I'd really like programming languages to introduce a 'super-private' property / field modifier, one that basically says 'You can only access this property through its accessor'.