'…!= null'或'null!= …'performance最好?

我写了两种方法来检查性能

public class Test1 { private String value; public void notNull(){ if( value != null) { //do something } } public void nullNot(){ if( null != value) { //do something } } } 

并在编译后检查它的字节码

 public void notNull(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field value:Ljava/lang/String; 4: ifnull 7 7: return LineNumberTable: line 6: 0 line 9: 7 StackMapTable: number_of_entries = 1 frame_type = 7 /* same */ public void nullNot(); Code: Stack=2, Locals=1, Args_size=1 0: aconst_null 1: aload_0 2: getfield #2; //Field value:Ljava/lang/String; 5: if_acmpeq 8 8: return LineNumberTable: line 12: 0 line 15: 8 StackMapTable: number_of_entries = 1 frame_type = 8 /* same */ } 

在这里使用两个操作码来实现if条件:第一种情况是使用ifnull- check顶层的堆栈值是null-,第二种情况是使用if_acmpeq- check顶层的两个值在stack-

那么,这会对性能产生影响吗? (这将帮助我certificate首先执行null在性能方面以及在可读性方面都是好的:))

比较生成的字节码几乎没有意义,因为大部分优化都是在JIT编译器运行时发生的。 我会猜测在这种情况下,表情是同样快速的。 如果有任何区别,那可以忽略不计。

这不是你需要担心的事情。 寻找大的图片优化。

如果速度(或者内存/无论是哪种情况)的增益可以忽略不计,则不要以可读性为代价进行优化。 我认为!=null通常更具可读性,所以使用它。

像这样的问题,很难知道JVM有多聪明(尽pipe答案“如果可能的话通常很聪明”,而且在这种情况下看起来很可能)。 但是可以肯定的是,testing它:

 class Nullcheck { public static class Fooble { } Fooble[] foo = {null , new Fooble(), null , null, new Fooble(), null, null, new Fooble() }; public int testFirst() { int sum = 0; for (int i=0 ; i<1000000000 ; i++) if (foo[i&0x7] != null) sum++; return sum; } public int testSecond() { int sum = 0; for (int i=0 ; i<1000000000 ; i++) if (null != foo[i&0x7]) sum++; return sum; } public void run() { long t0 = System.nanoTime(); int s1 = testFirst(); long t1 = System.nanoTime(); int s2 = testSecond(); long t2 = System.nanoTime(); System.out.printf("Difference=%d; %.3f vs. %.3f ns/loop (diff=%.3f)\n", s2-s1,(t1-t0)*1e-9,(t2-t1)*1e-9,(t0+t2-2*t1)*1e-9); } public static void main(String[] args) { Nullcheck me = new Nullcheck(); for (int i=0 ; i<5 ; i++) me.run(); } } 

在我的机器上,这产生了:

 Difference=0; 2.574 vs. 2.583 ns/loop (diff=0.008) Difference=0; 2.574 vs. 2.573 ns/loop (diff=-0.001) Difference=0; 1.584 vs. 1.582 ns/loop (diff=-0.003) Difference=0; 1.582 vs. 1.584 ns/loop (diff=0.002) Difference=0; 1.582 vs. 1.582 ns/loop (diff=0.000) 

所以答案是:不,根本没有意义的区别。 (而JIT编译器可以在重复运行的次数相同的情况下find额外的技巧来加速每个技巧。)


更新 :上面的代码运行一个临时基准。 使用JMH (现在它存在!)是帮助避免(一些)微小基准陷阱的好方法。 上面的代码避免了最糟糕的陷阱,但它没有给出明确的错误估计,并忽略了其他有时很重要的事情。 这几天:用JMH! 另外,如果有疑问,运行你自己的基准。 细节有时很重要 – 对于像这样简单的事情,并不是很常见,但是如果对你来说真的很重要,你应该检查一个尽可能接近你的生产条件。

除了避免在C中偶然赋值的辛苦智慧(这有利于将二元运算符置于左边)之外,我发现左边的常量更具可读性,因为它将关键值置于最显着的位置。

通常一个函数体只会使用一些variables,而且通常通过上下文的方式显示哪个variables正在被检查。 通过把常数放在左边,我们更接近模拟switchcase :给定这个variables,select一个匹配的值。 看到左边的价值,一个侧重于所select的特定条件。

当我扫描

 if (var == null) 

我读到:“我们正在检查var ,我们正在比较它的平等性,反对……啊,null。 相反,当我扫描

 if (null == var) 

我认为,“我们看到价值是否为零,是的,我们正在检查。 这是一个更强的认识

 if (null != var) 

我的眼睛只是立即采取了。

这种直觉来自习惯的一致性,倾向于阅读写作内容,并且写出喜欢阅读的内容。 一个人可以学习,但是这不是客观真实的,因为其他人在这里回答说左边的variables是更清楚的。 这取决于首先要expression什么样的方面。

看到字节码的差异是令人着迷的。 感谢分享。

差异将是可以忽略的,所以去最可读的( != null imo)

为了便于阅读,我会坚持(value!= null)。 但是你总是可以使用断言。

像这样微小的优化是编译器的工作,特别是在像Java这样的高级语言中。

虽然这里严格无关,但不要过早优化!

先将null似乎会生成一个额外的字节码,但除此之外,可能不会有性能差异。

就个人而言,我不担心performance,直到担心performance。

我会使用notNull()方法,只是如果你忘了! 并意外键入null = value

哦,如果你问最终的performance,不要创build额外的类或方法。 即使静态方法也需要一些时间,因为Java类加载器需要JIT加载它。

所以,无论何时你需要检查一个variables是否为null,你只要testing它

 if (x == null) 

要么

 if (null == x) 

坦率地说,我认为select其中之一的绩效奖金很容易被引入不必要方法的开销所抵消。

在编码过程中,你可以忽略这个非常精确的优化

正如你可以看到,不同的performance是非常less的。 不要担心小事情总是更好地关注algorithm。 显然可读性是一个因素。

从这个angular度来看,performance没有显着差异。

但是,首先写空字符来排错错误是有用的。

例如,如果您习惯写这个代码:

 if (obj == null) 

可能被误写为:

 if (obj = null) 

从编译器的angular度来看,这很好。

但是,如果您习惯于将代码编写为:

 if (null == obj) 

并写错了:

 if (null = obj) 

编译器会让你知道你在那一行犯了一个错误。

字节码只是源代码的简单翻译。