【发布时间】:2023-04-11 00:12:01
【问题描述】:
所以不久前有人问Is the ++ operator more efficient than a=a+1?。我以为我之前分析过这个,最初说a = a + 1和增量运算符++没有区别。事实证明,a++、++a 和 a += 1 都编译为相同的字节码,但 a = a + 1不是,如下所示:
public class SO_Test
{
public static void main(String[] args)
{
int a = 1;
a++;
a += 1;
++a;
}
}
输出:
例子:
public class SO_Test
{
public static void main(String[] args)
{
int a = 1;
a = a + 1;
a++;
a += 1;
++a;
}
}
输出:
简而言之,a = a + 1 发出 iload_1、iconst_1、iadd 和 istore_1,而其他只使用 iinc。
我试图合理化这一点,但我无法做到。在这种情况下,编译器是否智能不足以优化字节码?这些是不同的有充分的理由吗?这是由 JIT 处理的吗?除非我解释不正确,否则我似乎永远不应该使用a = a + 1,我认为这肯定只是一种风格选择。
【问题讨论】:
-
我觉得这里有两个方面1)编译时优化2)运行时优化。您现在观察到的与编译时优化有关。我认为我们需要在运行时优化之后决定应该/不应该使用。
-
这真的不是对字节码差异的全面分析;您所展示的只是字节码对于独立表达式语句是相同的。当您实际使用
a++或++a的结果 时会发生什么?编写了一个必须识别各种前/后增量模式的反编译器后,我记得存在更细微的差异。当然,实例字段、静态字段和数组元素的结果也往往不同。 -
@MikeStrobel 是的,我绝对应该不说详细的分析——实际上恰恰相反。不幸的是,目前我没有多少时间做任何详细的事情。或许是在休息...
-
看看我的Procyon反编译器;它可能会加快你的实验。编写一些测试,在不同的上下文中使用每种增量样式并比较反编译的结果。如果反编译器为所有三个上下文选择相同的运算符,则字节码可能是相同的。如果它重构了原始运算符,则可能存在差异。隔离这些情况,然后分析字节码(使用
-r运行 Procyon 以获取原始字节码)。 -
@MikeStrobel 谢谢,我去看看。