理解运算符优先级

Ald*_*ian 1 java string ternary-operator conditional-statements

正在修复我们的代码中的错误,发现这个行为不端的奇怪功能:

private String calculate(String a, String b) {
    return a == null ? "" : a + a != null && b != null ? "\n" : "" + b == null ? "" : b;
}
Run Code Online (Sandbox Code Playgroud)

匆匆忙忙,我只是添加了一些括号,让它像这样工作:

private String calculatePar(String a, String b) {
    return a == null ? "" : a + (a != null && b != null ? "\n" : "") + (b == null ? "" : b);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这不是最优雅的做法,但两者实际上都来自我编写的(简化的)测试用例示例.

现在我对有缺陷的第一个功能进行了一些测试,这就是我想到的:

  • 如果a == null,它将返回""(空字符串)
  • 如果a!= null且b == null,则返回null
  • else(如果a和b不为null)它将返回"\n"

现在最大的问题是:这是怎么发生的?我的意思是编译器很可能没有按照原始开发人员的意图放置自己的括号,但是你怎么能得到null呢?

Ala*_*anT 7

这更像是运算符优先级而不是连接.如果没有括号,编译器将使用" 运算符优先级"表来判断评估顺序.+具有比比较更高的优先级,因此语句被评估为

return a == null 
       ? "" 
       : (a + a != null && b != null) 
            ? "\n" 
            : ("" + b == null) 
                ? "" 
                : b;
Run Code Online (Sandbox Code Playgroud)

注意:我总是将嵌套的三元运算符语句缩进以帮助理解.

第1步:
a == null return""

第2步:
a!= null

检查(a + a!= null && b!= null)

(a + a!= null)总是如此,所以我们真的测试b!= null

b!= null,

返回"\n"

第3步:

如果b == null

检查(""+ b == null)

""+ b(null)永远不会等于null; 总是假的

所以,返回b,这是null.