obj == null vs null == obj

10

我过去一直使用以下方式检查 null 值:

if(null==obj)

当我编译我的代码并在反编译后查看.class文件时,我发现我的代码已经被更改为

if(obj==null)

我知道在 Java 中,null==objobj==null 没有区别。但是我很好奇编译器为什么会更改它呢?


6
你怎么知道是编译器改变了它而不是反编译器? - maerics
4
纯属猜测,但是:优化器通常会对表达式进行归一化处理,然后再使用这些归一化形式进行优化。这样做可以更轻松地对其进行优化,因为您只需要寻找一个特定的模式(因为类似的模式现在看起来像是同一种模式)。 obj==null 可能只是内部的归一化形式。 - yshavit
1
此外,您可以使用 javap -c 查看字节码本身,无需反编译。 - yshavit
1
很可能被编译为ifnonnull指令,因此原始顺序在.class文件中不再存在。 - Bubletan
1
有人投票以“主观性较强”为由关闭了这个问题。如果他们能解释一下背后的原因,那就太好了。 - bajji
显示剩余8条评论
2个回答

9
编译器没有改变任何内容。它忠实地将 if (null == obj)if (obj == null) 编译成不同的字节码,反编译器又将其转换回相同的 Java 代码。
与右侧的 null 进行比较,即:
if (o == null) {
    ...
}

使用ifnonnull指令,将其转换为以下字节码:

0: aload_0
1: ifnonnull     ...

与左侧的null进行比较,即:
if (null == o) {
    ...
}

被翻译成不同的字节码,使用if_acmpne指令:

0: aconst_null
1: aload_0
2: if_acmpne     ...

在理论上,反编译器拥有足够的信息来确定参数在源文件中的排序方式。然而,在两种排序方式下它们产生了相同的代码。

1
在我的javac(Oracle 1.7.0_67)上,情况并非如此。操作被编译为aconst_nullaload_1if_acmpne(最后一个是“如果不相等”)。Java 1.8.0_45也是如此。我还没有尝试过Java 9。 - yshavit
@yshavit 你是对的,编译器生成了两个不同的字节码集,所以混淆事情的是反编译器。谢谢! - Sergey Kalinichenko

0

在Java中,它们是相同的,因为if语句中只能包含布尔表达式。这只是程序员和团队协议如何编写的一种编码风格偏好。

null != a是编程语言(如Java、C++)中的一种旧实践,也称为Yoda条件。

由于可以编写if (a = null)并意外地将null赋给a,因此首先写入null是防止发生此意外的保护措施。

大多数程序员使用a == null只是因为它看起来更简单易懂。可能这就是编译器/反编译器将它们放置在这样的顺序中的原因,也许还有其他原因...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接