object == null或null == object?


96

我听到有人null == objectobject == null 检查更好

例如:

void m1(Object obj ) {
   if(null == obj)  // Is this better than object == null ? Why ?
       return ;
   // Else blah blah
}

有什么原因还是这是另一个神话?感谢帮助。


271561年和1957836年的伪造(但此人说的是“用Java写”)
吉舒2010年

20
Java与C#不同
Jijoy

5
如果一个显著的性能优势,那么可以肯定的编译器会优化它...
安德烈亚斯·多克

作为null参考,默认的操作过程应该是抛出NPE。一些不错的库(例如JDK7 Java库)具有类似的方法public static <T> T notNull(T obj) { if (obj == null) { throw new NullPointerException(); } else { return obj; } }。也有@NonNull(或@Nonnull?),但是被“擦除”了。
汤姆·霍顿

Answers:


140

这可能是从C那里学来的一种习惯,可以避免这种拼写错误(单笔=而不是双笔==):

if (object = null) {

==在Java中,将常量放在左侧的约定并不是真正有用的,因为Java要求将表达式中的表达式if计算为一个boolean值,因此,除非常量为a boolean,否则无论哪种方式放置,都会出现编译错误。论点。(如果是布尔值,则==无论如何都不应该使用...)


4
这对于Java来说不是一个非常有用的习惯,因为输入错误会导致Java上的编译错误
radai


3
@Chandru为布尔值,可以使用x.booleanValue()!x.booleanValue()x == truex == false在某种条件下表达难闻的气味,恕我直言
劳伦斯·贡萨尔维斯

2
他在这里检查null。在某些情况下,他真的必须检查布尔值是否为null,因为null既不是true也不是false。
Chandra Sekar'3

1
习惯于null == object仅使用以确保我们不会用错字误覆盖对象完全不应该成为用例。这意味着,我们正在训练自己,既然我先犯了“ null”,即使我犯了一个错误,也可以。这并不意味着代码可以按预期工作。即使null = object在位置给出null == object,该程序也无法按预期运行!那么遵循这个约定毫无意义!
VanagaS

32

就像其他人所说的那样,这是从C语言中学到的避免输入错误的习惯-尽管即使在C语言中,我也希望有足够高的警告级别的体面的编译器能够发出警告。正如Chandru所说,如果您使用类型变量Boolean(不在示例代码中),则以这种方式与Java中的null比较只会导致问题。我会说这是一种非常罕见的情况,而不是值得在其他任何地方更改代码编写方式的情况。(即使在这种情况下,我也不会费心地反转操作数;如果我想清楚的足够多,可以考虑将它们反转,那么我敢肯定我可以算出等号。)

什么也没有被提及的是,很多人(当然我自己在内)发现的if (variable == constant)形式可读性更强-这是表达自己的更自然的方式。这是一个不要盲目地从C语言复制约定的原因。在假定一种环境中有用的东西在另一种环境中有用之前,您应该始终质疑实践(如此处所做的:)。


3
我同意您所说的每个词,尤其是“盲目复制约定”部分。我现在正在阅读代码,null =对象样式使我非常烦恼,以至于我查找并来到这里。编码人员在想什么?
Adrian M

28

在Java(1.5+)中,这没有什么价值,除非对象的类型为Boolean。在这种情况下,这仍然很方便。

if (object = null)如果object为Boolean,则不会在Java 1.5+中导致编译失败,但会NullPointerException在运行时抛出。


您可能是说这将导致编译失败:)
vava 2010年

7
不,当object为Boolean时,不会导致编译错误。
Chandra Sekar 2010年

除布尔值外,其他所有对象类型都不相同吗?
Ciro Santilli郝海东冠状病六四事件法轮功

2
对于非布尔类型,该代码将不会编译,因为表达式“ object = null”的类型将不是布尔值。由于自动装箱,它将编译为布尔值。
Chandra Sekar

但是,为什么这种行为是布尔型的呢?有什么理由吗?
Rohit Banga

9

在Java中,没有充分的理由。

其他几个答案都声称这是因为您可能会不小心将其赋值而不是相等。但是在Java中,您必须在if中使用布尔值,因此:

if (o = null)

将无法编译。

在Java中这唯一重要的是变量是否为布尔值:

int m1(boolean x)
{
    if (x = true)  // oops, assignment instead of equality

4
但是你为什么会写== true或同样地写== true == true
汤姆·霍顿

7
没有充分的理由写作== true。但是我在职业生涯中看到了很多糟糕的代码,以至于我不再问为什么有人会写东西而只是接受有人写了不必要的/可疑的代码。
R Samuel Klatchko

1
确实,仍然有很多糟糕的代码在四处游荡,x == true因为它们可能会被错误地编写为“糟糕”代码x = true,因此将其更改true == x为just 并没有多大意义x
Holger

9

这也与以下方面密切相关:

if ("foo".equals(bar)) {

如果您不想处理NPE,这很方便:

if (bar!=null && bar.equals("foo")) {

可能很方便,但可能很危险blue-walrus.com/2010/11/…–
奥利弗·沃特金斯

@OliverWatkins:我发现这篇文章比较薄弱。假设变量的类型为int。如果未初始化,则该值为0,并且该商品的承诺不成立。字符串是对象而整数是基元这一事实与程序员可能忘记初始化变量的事实无关。在这个问题中,我们只需解决null字符串比较问题。
cherouvim 2014年

@cherouvim事实int是一个基本类型相关的,因为这是不可能调用equals上的int,因此,存在在讨论到阉使用没有点x.equals(constant)constant.equals(x)int值。对于Integer值,默认值为null而不是0
Holger

5

这个技巧可以防止v = null打字错误。

但是Java只允许将布尔表达式作为if()条件,因此这种技巧没有太大意义,编译器仍然会找到那些错别字。

对于C / C ++代码,这仍然是有价值的技巧。


3

出于同样的原因,您可以在C语言中执行;分配是一个表达式,因此您将文字放在左侧,这样,如果不小心使用=而不是,就不能覆盖它==


但是,这在Java中仅是布尔类型的问题,对吗?任何其他类型的赋值都不会具有布尔类型,并且应导致编译器错误。
Scott Smith'3

1
不,Java编译器会按照您喜欢的顺序捕获这种错字
vava 2010年

@Jijoy-我认为这与性能无关。这听起来像是C语言中的一个老技巧,以避免在条件表达式内执行可怕的赋值错误。这个想法是,如果您试图检查是否x等于equals 5,则当您错误地键入时if (x = 5),它将安静地编译(并且始终计算为true,而与的值无关x)。但是,如果您习惯总是先指定文字:'if(5 = x)',则编译器可以仔细检查您的工作,并节省调试器的工作时间。现代编译器使这种习惯变得不必要。
斯科特·史密斯史密斯,2010年

6
-1:如果您不小心使用了=,它将无法在Java中进行编译;因此C的原因不适用。
乔恩·斯基特

从技术上讲,如果obj是类型java.lang.Boolean(大B),则可以有所作为(我认为,实际上没有尝试过)。
汤姆·哈特芬

3

那是给那些喜欢在左边加上常数的人。在大多数情况下,左侧具有常量将防止引发NullPointerException(或具有另一个nullcheck)。例如,String方法equals也会执行空检查。将常量保留在左侧将使您不必编写其他检查。另外,稍后还将执行另一种方法。左侧具有null值只是保持一致。

喜欢:

 String b = null;
 "constant".equals(b);  // result to false
 b.equals("constant");  // NullPointerException
 b != null && b.equals("constant");  // result to false

NPE的这种隐藏只会在下游更加难以发现错误
Oliver Watkins

2

用不同的方式是尤达条件写

在java中

String myString = null;
if (myString.equals("foobar")) { /* ... */ } //Will give u null pointer

尤达条件

String myString = null;
if ("foobar".equals(myString)) { /* ... */ } // will be false 

1

与以下代码进行比较:

    String pingResult = "asd";
    long s = System.nanoTime ( );
    if ( null != pingResult )
    {
        System.out.println ( "null != pingResult" );
    }
    long e = System.nanoTime ( );
    System.out.println ( e - s );

    long s1 = System.nanoTime ( );
    if ( pingResult != null )
    {
        System.out.println ( "pingResult != null" );
    }
    long e1 = System.nanoTime ( );
    System.out.println ( e1 - s1 );

输出(多次执行后):

null != pingResult
325737
pingResult != null
47027

因此,pingResult != null是赢家。


7
在另一个循环中运行测试!或者只是切换IF语句。长话短说:没有区别!第一个循环总是较慢。
Marcel Jaeschke

在此测试中,pingResult始终为非null。pingResult为null的时间会怎样?我打赌它是独立于平台的,但是在我的Oracle Java 1.6 / Linux堆栈上,结果(在循环中)几乎是均匀的,除非pingResult为null,这两项检查都快了百分之几。
Ogre Psalm33

1
如果将“ pingResult!= null块放在null!= pingResult块之前,则结果将类似于“ pingResult!= null 325737”
Sola Yang

正如@Sola Yang所说,如果您之前将pingResult!= null放进去,您会发现它比null!= pingResult需要更多的时间。如果pingResult!= null快于null!= pingResult,则IDE(例如IntelliG,Eclipse等)将发出警告,要求开发人员强制使用此角色;)
adil.hilmi

1

由于其具有可交换性,因此object == null和之间的唯一区别null == objectYoda版本)具有认知性质:读者如何读取和消化代码。虽然我不知道确切的答案,但我确实知道我个人更喜欢将要检查的对象与其他对象进行比较,而不是将其他内容与要检查的对象进行比较(如果有任何意义)。从主题开始,然后是与其进行比较的值。

在某些其他语言中,此比较样式更有用。

但是,为了防止出现一般的“ =”符号,我认为写作null == object防御性编程的错误行为。围绕此特定代码的更好方法是通过junit测试保证行为。请记住,遗漏“ =”的可能错误不取决于方法的输入参数-您不取决于其他人对该API的正确使用-因此junit测试可以完美地防止这种情况的发生。无论如何,您将要编写junit测试来验证行为。缺少的“ =”自然属于范围。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.