【问题标题】:Checking for null - what order? [duplicate]检查 null - 什么顺序? [复制]
【发布时间】:2015-12-07 13:41:42
【问题描述】:

当检查空值时,我使用这个:

String str;

if(str == null){
    //...
}

但我也见过这个:

if(null == str){
    //...
}

使用其中一个有什么优势吗?还是只是为了提高可读性?

【问题讨论】:

  • 如果您使用它来防范空参数,T Objects.requireNonNull(T[, String]) 可能会引起您的兴趣。
  • 如果检查布尔条件以防止在您的意思是 if(value == true) 时键入 if(value = true) 之类的人为错误,它确实会产生差异(在 Java 中)。这种事情可能会导致容易完成且难以追踪的错误!

标签: java


【解决方案1】:

第二个版本 (null == str) 称为 yoda 条件

它们都导致相同的行为,但第二个有一个优点:当您忘记一个 = 时,它可以防止您意外更改变量。在这种情况下,编译器会在该行返回错误,并且您的代码不会有一些奇怪的行为以及由此产生的调试。

【讨论】:

  • 视情况而定。正如用户 thkala 正确指出的那样,在 Java 中这并不重要。但是,在 C 语言中,现代编译器(例如 LLVM 的 Clang)会通过“将赋值结果用作不带括号的条件”来警告您。
  • 感谢 Sirko,这对我来说很有意义 :)
【解决方案2】:

null == x 约定通常出现在熟悉 C 的人编写的代码中,其中赋值也可以是表达式。一些 C 程序员编写这样的代码,这样如果他们错过了 = in

if (NULL == ptr)...

代码不会编译,因为NULL = ptr 不是一个有效的赋值。这可以防止在代码库中引入相当隐蔽的错误,尽管现代 C 编译器使此类约定过时,只要注意启用并读取生成的警告... p>

这种编码风格在 Java 中从来没有任何用处,在 Java 中,引用赋值不能用作布尔表达式。它甚至可以被认为是违反直觉的;在他们的自然语言中,大多数人会说“如果 X 为空......”,或者 “如果 X 等于 17......”,而不是 "如果 null 等于 X...".

【讨论】:

  • 这种编码风格在 Java 中从来没有任何用处想象一下 boolean b=... if (b=isXXX()){...} 并与 boolean b=... if (isXXX()==b){} 进行比较
  • @bestsss:我编辑了我的答案以澄清这一点。也就是说,在某些情况下,您的第二个 sn-p 很可能比第一个更直观,这取决于 b 是否可以被视为局部常量。 if (false == myFlag)... 虽然不太一样...
  • 要点是,在第一个 sn-p 中,如果等效于 boolean b;... b=isXXX(); if (b){...},这是有效的,但它也可能是一个错误。例如 boolean b=isYYY(); if (b=isXXX()){} 不能比较 isYYY() to isXXX() - 实际上 java 它不太容易在 C 中出现同样的错误,但仍然有可能。
  • @bestsss:同意,if (b == false)... 是有效代码,Yoda 风格的条件确实可以防止此处出现错误。不过,这并没有使它变得更加清晰或可维护……
【解决方案3】:

除了可读性之外,两者之间没有区别。使用对您更有意义的那个。

【讨论】:

  • 确实如此。虽然我可以补充一点,我从未见过有人使用“null == str”变体,所以我建议使用第一个版本,因为它更传统。
  • 后者听起来像是尤达条件。
  • 这不是在过去也用于缓解使用单个= 而不是== 的问题吗? if (str=null) 有效,但 if (null =str) 无效。
  • @climbage 是的,但是在Java中,if语句中只能使用布尔表达式,所以这里真的没有区别。
  • @Jeffrey 是的,我只是想这可能有助于解释为什么你会首先看到这个表达式。
【解决方案4】:

正如您所说,可读性是最重要的原因。大声读出来, (null == str) 读起来不好。这几乎就像从右到左阅读一样。 (str == null) 读起来好多了。

另外,我认为需要考虑以下几点:

if (str != null)  
if (str == null)

对比

if (null != str)
if (null == str)

我希望正数 (str == null) 和负数以相同的方式写入,这是我偏爱顶部集合的另一个原因。

【讨论】:

    【解决方案5】:
    if (null == str) {
    }
    

    是来自 c/c++ 的编程习惯,其中赋值运算符 = 可用于解析真/假语句。例如在c中如果你想检查我是否可以在c/c++中打开一个流,你可以

    if (myStream = openStream())
    

    在一行中设置打开和分配。然而,这意味着人们经常在他们的意思是== 时输入=,这将是c 中的有效语法:例如if (x = 5) 将始终解析为true,而他们真正的意思是if (x ==5)。所以人们写if (5 == x),所以如果你遗漏=,你的代码将无法编译。

    这不适用于 java。

    【讨论】:

      【解决方案6】:

      没有真正的区别。然而,第二个被认为不太容易出错。在第一种情况下,如果您尝试这样做,您将不会收到错误

      String str;
      
      if(str = null){
      }
      

      这是你通常不会在条件句中做的事情。

      此外,您可以先考虑实际情况,这是一个很好的做法。

      【讨论】:

      • 您实际上在 Java 中得到了一个错误:错误,不兼容的类型。找到 java.lang.String 必需的布尔值。
      【解决方案7】:

      if(a==b) {}if(b==a) {} 相同,如果 b 为空,也是如此。就功能而言,这只是样式/顺序的差异,至少在 java 中是这样。

      【讨论】:

        【解决方案8】:

        一些开发人员认为var == nullnull == var 更容易出错。他们的论点是您可能不小心分配了变量而不是进行空值检查。

        但只有当您针对null 测试的变量是Boolean 时,您可能会意外使用= 而不是==,它才会编译。

        Boolean checked = Boolean.TRUE;
        if(checked = null){ // accidentally assigned null and compiles
        }
        

        只有在这种情况下赋值才能编译,因为条件表达式必须计算为布尔值。请参阅JLS-14.9. 由于赋值表达式本身的计算结果为布尔类型,因此它可以编译。但是你会在runtume 得到一个NullPointerException,因为java 会尝试解开checked 变量null

        如果你使用任何其他类型然后Boolean 你会得到一个编译器错误。例如

        String str = "hello";
        if(str = null){ // compiler error, because str = null doesn't evaluate to a boolean
        }
        

        我的结论是错误情况极为罕见,您可以轻松编写检测此类错误的单元测试。

        因此,以更易读的方式编写 if 语句。

        我认为“if name is null”比“if null is name”更有意义。

        【讨论】:

          猜你喜欢
          • 2011-01-21
          • 2012-04-27
          • 1970-01-01
          • 2019-10-31
          • 2018-12-17
          • 2018-04-20
          • 2012-04-06
          相关资源
          最近更新 更多