我正在使用此代码进行测试:
public class TestNull {
public void leftComparison(String s) {
if (s == null);
}
public void rightComparison(String s) {
if (null == s);
}
}
我用javac 1.8.0_05编译它,然后检查了字节码:
public class TestNull {
....
public void leftComparison(java.lang.String);
Code:
0: aload_1
1: ifnonnull 4
4: return
public void rightComparison(java.lang.String);
Code:
0: aconst_null
1: aload_1
2: if_acmpne 5
5: return
}
显然,leftComparison
被编译为在rightComparison
推送和弹出2时在堆栈上推送和弹出1个变量。我推测leftComparison
因此比rightComparison
略高效}?
我想知道编译器为什么不重写rightComparison
的代码?在我看来,这两个比较应该在语义上是等价的,对吧?
答案 0 :(得分:5)
Java字节码编译器在优化方面做得很少。严重的优化工作几乎全部由JIT编译器完成。
我想知道编译器为什么不重写rightComparison的代码?
因为重写它没有意义。 JIT编译器应该能够处理它们,并且很可能为这两个版本生成最佳(本机)代码。 (如果您感兴趣,可以检查一下。有方法可以查看JIT编译器生成的本机代码。)
(另请参阅@ codenheim&#39的答案以获得更多技术解释。)
在我看来,这两个比较应该在语义上等同,对吗?
这是正确的......但它并不意味着字节码编译器有义务为两个版本生成相同的字节码序列。
这里的真正的课程是字节码编译器生成的字节码序列告诉您很少关于代码实际执行的方式。您从阅读字节码中得出的任何性能结论都是高度怀疑。
答案 1 :(得分:2)
实际上,字节码相当于中间代码。过早优化或优化两次的投资回报率很低。
答案 2 :(得分:1)
几乎是因为"它是如何写的"。比较考虑了左手变量并将其与右侧进行比较。当您说null == s
时,您说'#34;将null
与此变量进行比较"所以代码定义了一个常量null
来比较。编译器只是将其他比较优化为非空检查。