赋值时,Java三元行为异常。Java在幕后为此做了什么?


10

几天前,我遇到了一个令人着迷的场景,我找不到任何有关Java如何或为什么使以下情况发生的文档。(此代码段只是该错误的简化形式。)

    @Test
    public void test() {
      boolean bool = false;
      Integer intVal = Integer.valueOf(5);
      Long longVal = null;
      Long result = bool ? intVal : longVal;

      System.out.println(" > " + result);
   }

在上面的代码段中:

如果bool = true,则得到的值为'5';

但是如果bool = false,则在尝试评估三元运算时会得到空指针异常。不是打印语句。


为了解决这个问题,我只是将“结果”更改为

Long result = bool ? Long.valueOf(intVal) : longVal;

这样做,将给出我所需的预期行为:

如果bool = true,则得到的值为'5';

但是如果bool = false,那么您将获得'null'


现在有趣的部分是,如果将其拆分为普通的if / else语句,那么java不会让您编译

longVal = intVal; 

但是它不能通过三元运算符来捕获。那么,Java在做什么以使其在原始代码段中为空点?

(java 11)

Answers:


10

执行此操作时:

Long result = bool ? intVal : longVal

该表达式返回a long,如果bool为false,则尝试将其拆箱null为Long值以适合该result变量并抛出NPE。

执行此操作时:

Long result = bool ? Long.valueOf(intVal) : longVal

该表达式已经返回,Long因此无需取消装箱,并且已将null值成功分配给result变量。

参考:

如评论部分所述,为了更好地理解为什么会发生,请检查JLS的以下部分:


我很惊讶您使用不同的参考表15.25 A到E,其中“整数” /“长”会产生bnp(整数,“长”)是“显而易见的”。
马特

好答案。通常,当我完全不知道里面发生了什么时,我建议您看一下已编译的字节码,该字节码几乎准确地揭示了所描述的内容。至少在提取最小的代码片段时,这或多或少是训练,如何阅读和理解它的问题。
一月于

正如JLS所述,第5.6.2节说:“如果任何操作数是引用类型,它将进行拆箱转换”;然后“应用[..]简化原始转换(§5.1.2)”
Diego Magdaleno
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.