你能简单解释一下我理解这个吗?
答案 0 :(得分:16)
首先,Java语言规范没有说明时序。但假设我们使用的是典型的编译器,如Suns javac,我们发现上述所有示例(a++
,++a
,a += 1
,a = a + 1
)都可以编译进入类似的东西:
iinc
指令,处理变量:
iload_<variable>
iinc <variable>, 1
istore_<variable>
iadd
instuction,使用堆栈(此处使用变量1
作为存储空间):
iload_1
iconst_1
iadd
istore_1
编译器可以选择最好的编译方式。例如。他们之间存在没有区别。而且这些陈述之间不应该有任何区别 - 它们都表达相同的东西 - 在数字中添加一个。
有人说,iinc
和iadd
版本都可以使用JIT编译为快速和平台相关的东西,最后我会假设一个普通的运行时将两个版本编译成相同的汇编代码。
使用我的编译器,* jdk1.6.0_20 *“增量”方法甚至使用相同的指令。
public class Test {
public static void main(String[] args) {
int a = 0;
a = a + 1;
a += 1;
a++;
++a;
}
}
这是反汇编:
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iinc 1, 1 // a = a + 1;
5: iinc 1, 1 // a += 1;
8: iinc 1, 1 // a++;
11: iinc 1, 1 // ++a;
14: return
}
答案 1 :(得分:3)
查看生成的字节码:
public static void main(String[] args) {
int x = 1;
int y = 1;
int z = 1;
int a = 1;
int b = 1;
x = x + 1;
y++;
++z;
a += 1;
b += 2;
}
生成(使用javap -c classname
)
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: iconst_1
5: istore_3
6: iconst_1
7: istore 4
9: iconst_1
10: istore 5
12: iload_1
13: iconst_1
14: iadd
15: istore_1
16: iinc 2, 1
19: iinc 3, 1
22: iinc 4, 1
25: iinc 5, 2
28: return
所以使用(jdk1.6.0_18):
x = x + 1
创建
12: iload_1
13: iconst_1
14: iadd
15: istore_1
,而
y++;
++z;
a += 1;
所有结果都是
iinc
然而,在我的笔记本电脑上进行粗略的性能测试导致两者之间的运行时间没有差别(有时++ x更快,有时x = x + 1更快),所以我不担心性能影响。
答案 2 :(得分:2)
不,不会有任何明显的差异。使用您认为最具可读性的内容(通常为a++
。)
代码优化的第一条规则:不要。
答案 3 :(得分:1)
编译器应该优化,根本不应该有任何区别。 但请记住,前缀增量运算符可能(它取决于编译器)比后缀等价物更快(在C ++和C#中也是如此):
++a
比a++
快,因为后缀运算符必须创建一个临时变量..考虑一下它们的实现:
前缀:
a = a + 1;
return a;
后缀:
int tmp = a;
a = a + 1;
return tmp;
答案 4 :(得分:0)
a ++更快。它转换为汇编程序的INC命令。但我认为JVM会优化a = a + 1,所以你不需要关心它。
答案 5 :(得分:0)
它是一样的,现在随着编译器优化不应该意识到这些东西,以提高你的性能检查其他更大的问题,如allocs:)