java - 三元表达式有时会绕过编译器检查验证

标签 java eclipse compilation expression ternary-operator

由于某种原因,以下代码编译正常:

public double getSomeDouble() {
    return "" != null ? 3.7d : null;
}

我通常期望 Eclipse将其标记为错误(null 不能转为 double 原语)。

只是为了支持我的假设,这段代码不起作用:

public double getSomeDouble() {
    return null;
}

Eclipse 会将 return null 行标记为错误,说明:

Type mismatch: cannot convert from null to double

为什么前面的代码片段不一样?!

最佳答案

这是由于 autoboxingautounboxing .如果您查看字节码(如下),您可以看到对 Double.valueOf 的调用(将 3.7d 装箱)和 Double#doubleValue (将条件表达式的结果拆箱)。条件运算符的操作数必须是相同的类型,因此编译器有效地将您的代码转换为:

public double getSomeDouble() {
    return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}

...因为 Double 是它可以为 3.7dnull 找到的最具体的常见类型。

我使用了一个字符串参数(以消除围绕不变表达式 ""!= null 的编译器优化,编译器可以判断它永远不会是真的):

public double getSomeDouble(String str) {
     return str != null ? 3.7d : null;
}

实际上变成了:

public double getSomeDouble(String str) {
    return (str != null ? Double.valueOf(3.7d) : null).doubleValue();
}

...当我为 str 传入 null 并尝试调用 doubleValue() 时,确实在运行时得到了 NPE在 null 上。

这是我的 getSomeDouble(String) 的字节码(来自 javap -c MyClass):

  public double getSomeDouble(java.lang.String);
    Code:
       0: aload_1
       1: ifnull        13
       4: ldc2_w        #7                  // double 3.7d
       7: invokestatic  #9                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      10: goto          14
      13: aconst_null
      14: invokevirtual #10                 // Method java/lang/Double.doubleValue:()D
      17: dreturn

关于java - 三元表达式有时会绕过编译器检查验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29624183/

相关文章:

java - 如何在类编译后运行java程序

java - 使用 Apache Tomcat 在 Eclipse 中运行 RESTful Web 服务

java - 如何运行已粘贴到我的程序中的 Java 代码

java - Axis 故障 : (500)Internal Server Error

java - Java 8 时间 API 的 ObjectMapper 配置

java - eclipse 中的 Gradle JAVA_HOME 路径

emacs - 如何在Emacs中设置编译的默认目录?

javac:无效的目标版本:1.7

java - java中如何将json数据导出到excel表中

java - Oracle SODA API for java - 异常 - 缺少右括号