执行
之间是否有任何差异Field field = something.getSomethingElse().getField();
if (field == 0) {
//do something
}
somelist.add(field);
与
if (something.getSomethingElse().getField() == 0) {
//do something
}
somelist.add(something.getSomethingElse().getField());
通过getter对字段的引用会导致性能损失还是与引用已分配的变量相同?我理解变量只是对内存空间的引用,所以getter应该只是成为那个记忆空间的另一种方式。
请注意,这是一个学术问题(只是好奇的学校)而不是实用的问题。
答案 0 :(得分:11)
这是一个微不足道的损害。不要太在乎自己,否则你会成为过早优化的牺牲品。如果你的申请很慢,这不是原因。
答案 1 :(得分:7)
假设getSomethingElse()
被定义为
public SomethingElse getSomethingElse() {
return this.somethingElse;
}
性能差异将是最小的(如果它被内联则为零)。然而,在现实生活中,你不能总是确定是这种情况 - 可能会在幕后发生一些处理(不一定在对象本身,但是,例如,通过AOP代理)。因此,将结果保存在变量中以便重复访问可能是一个好主意。
答案 2 :(得分:5)
通过getter访问变量会导致方法调用存在差异。在某些情况下,JVM可能会优化方法调用,但它是方法调用。
也就是说,如果您的代码中最大的瓶颈或性能问题是来自访问器方法的开销,我会说您没有太多担心。
答案 3 :(得分:4)
存在性能损失(可能很小,可以忽略不计)但是,JVM可能会内联这些以及所有调用来提高性能。
如果你以第二种方式离开它会更好。
答案 4 :(得分:3)
如果你有一个好的JVM,就像Sun的HotSpot那样。它将内联并编译(到本机代码)getter。
使用getter通常是一种非常好的做法,作为一种防御措施,以及一般的信息隐藏。
答案 5 :(得分:2)
如果使用Java编写Android应用程序,请注意以下几点: http://developer.android.com/training/articles/perf-tips.html#GettersSetters
在像C ++这样的本地语言中,使用getter是常见的做法(i = getCount())而不是直接访问该字段(i = mCount)。这个 是C ++的一个很好的习惯,并且经常在其他对象中实践 面向C#和Java的语言,因为编译器通常可以 内联访问,如果您需要限制或调试字段访问 您可以随时添加代码。
然而,这在Android上是一个糟糕的主意。虚拟方法调用是 比实例字段查找昂贵得多。这很合理 遵循常见的面向对象编程实践并拥有 公共界面中的getter和setter,但是在一个类中 应始终直接访问字段。
没有JIT,直接字段访问速度比调用a快3倍 琐碎的吸气剂。使用JIT(直接现场访问便宜) 访问本地),直接字段访问速度比快速快7倍 引用一个微不足道的吸气剂。
请注意,如果您使用的是ProGuard,则可以充分利用它们 世界,因为ProGuard可以为您内联访问器。
答案 6 :(得分:0)
如果该方法是一个简单的吸气剂,不涉及任何处理,则不是问题。如果它涉及大量计算,那么财产就无法做到你想做的事情。
我担心任何差异的唯一一次是在一个紧凑的循环中进行大量的迭代(数千次)。即便如此,如果您使用方面来编织额外的处理(例如日志记录),这可能只是一个问题,这可能涉及创建数千个额外的对象(例如JoinPoints和参数自动装箱)以及由此产生的GC问题。
答案 7 :(得分:0)
我不担心性能差异。你最好不要考虑它,而是花时间在一个真实的场景中分析你的代码。您很可能会发现程序的缓慢部分不在您认为的位置。
答案 8 :(得分:0)
这篇文章讨论的是CLI VM而不是JVM,但每个人都可以做类似的事情,所以我认为它是相关的。
我正在以一种特殊的方式为我的JIT处理这个特殊问题。请注意,此处的描述是概念性的,并且出于性能原因,代码以稍微不同的方式实现它。当我加载一个程序集时,如果它只返回一个成员字段,我会在方法描述符中做一个注释。当我稍后JIT其他方法时,我将所有call
指令替换为字节代码中的这些方法,并使用ldfld
指令,然后将其传递给本机代码生成器。通过这种方式,我可以:
ldfld
对JIT的处理时间比call
少。)毫无疑问,虚拟机技术领域的知名人士已经在他们的产品中实现了类似(并且可能更好)的东西。