三元表达式有时会绕过编译器检查验证
Ternary expression sometimes bypasses compiler checks validations
由于某些原因,以下代码编译正常:
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
为什么它在前面的代码片段中没有说同样的话?!
这是由于 autoboxing and autounboxing。如果您查看字节码(下方),您可以看到对 Double.valueOf
(对 3.7d
进行装箱)和 Double#doubleValue
(对条件表达式的结果进行拆箱)的调用。条件运算符的操作数必须是同一类型,因此编译器有效地将您的代码转换为:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
...因为 Double
是它可以为 3.7d
和 null
.
找到的最具体的常见类型
我使用了一个字符串参数(以消除围绕不变表达式 "" != 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()
时,确实在运行时遇到了 NPE。
这是我的 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
由于某些原因,以下代码编译正常:
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
todouble
为什么它在前面的代码片段中没有说同样的话?!
这是由于 autoboxing and autounboxing。如果您查看字节码(下方),您可以看到对 Double.valueOf
(对 3.7d
进行装箱)和 Double#doubleValue
(对条件表达式的结果进行拆箱)的调用。条件运算符的操作数必须是同一类型,因此编译器有效地将您的代码转换为:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
...因为 Double
是它可以为 3.7d
和 null
.
我使用了一个字符串参数(以消除围绕不变表达式 "" != 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()
时,确实在运行时遇到了 NPE。
这是我的 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