【问题标题】:Ternary expression sometimes bypasses compiler checks validations三元表达式有时会绕过编译器检查验证
【发布时间】:2015-06-19 21:02:21
【问题描述】:

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

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

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

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

public double getSomeDouble() {
    return null;
}

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

类型不匹配:无法从 null 转换为 double

为什么在之前的代码sn-p上没有说同样的话?!

【问题讨论】:

标签: java eclipse compilation expression ternary-operator


【解决方案1】:

这是由于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 时,当它试图在null 上调用doubleValue() 时,确实在运行时得到了一个N​​PE。

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

公共双 getSomeDouble(java.lang.String); 代码: 0:aload_1 1: ifnull 13 4: ldc2_w #7 // 双倍 3.7d 7: invokestatic #9 // 方法 java/lang/Double.valueOf:(D)Ljava/lang/Double; 10:转到 14 13: 常量空值 14: invokevirtual #10 // 方法 java/lang/Double.doubleValue:()D 17:返回

【讨论】:

  • 虽然错误原因现在很清楚,但我仍然想设置 eclipse 编译器来为我跟踪那些不是(在运行时为时已晚:(),你知道方法吗?跨度>
  • @MaximRahlis:恐怕我没有。看起来 Guillaume 找到了您可能想观看的功能请求...
  • 谢谢你们!一定会看 eclipse 功能请求线程。
猜你喜欢
  • 2021-06-27
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
相关资源
最近更新 更多