[英]Why does returning null for a primitive work in this case?
这段丑陋的代码确实可以编译,但如果s == null
则抛出 NPE
public static boolean isNullOrEmpty(String s)
{
return s != null ? s.isEmpty() : null;
}
虽然这不是(如预期的那样):
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return null;
}
我知道他们两个都是错误的,但当我在我们的源代码中找到第一段代码时,我很惊讶它确实编译了。
编辑:这是来自 Java 7 的 JLS 的相关部分。我猜第一个语句适用,但粗体语句适用。
15.25 条件运算符? :
[...]
条件表达式的类型确定如下:
[...]
[...]
第一个有一个三元运算符,其结果类型为Boolean
。 NPE 正在将null
转换为boolean
。
它实际上是这样的:
Boolean temp = s != null ? s.isEmpty() : null; //no problems here
return temp; //crash when temp==null
第二个是试图返回错误的类型(对象而不是原始类型)——因此无法编译。
三元运算符使用 JLS 中引用的规则进行自动装箱:
这条规则是必要的,因为条件运算符 (§15.25) 将装箱转换应用于其操作数的类型,并将结果用于进一步的计算。
问题在于 Java 中的自动装箱。 问题是由于第二个操作数不是第三个。
public static boolean isNullOrEmpty(String s)
{
return s != null ? null : null;
}
这段代码不会编译
三元运算符需要为两个操作数找出最合适的返回类型。
因此,它允许对返回类型进行一些“修饰”。
如您的第一个代码片段所示:
public static boolean isNullOrEmpty(String s)
{
return s != null ? s.isEmpty() : null;
}
s.empty()
返回原始boolean
,而第三个操作数返回null
。 所以最具体的常见返回类型是Boolean
。 编译器的工作就像将行替换为:
return s != null ? s.isEmpty() : (Boolean)null;
返回类型方法需要一个boolean
原语,所以编译器说:“酷,我只需要拆箱我的结果。”不幸的是, null
不是拆箱的,会导致难看的 NPE。
用你的第二个片段:
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return null;
}
没有对预返回类型进行额外的“润色”,因为编译器没有链接这段代码中的两个返回语句 => 对它来说可能是一项太难的工作。
因此,在这种情况下,代码甚至无法编译是合乎逻辑的,因为null
与Boolean
没有关联,所以。 不会发生任何演员表。
要编译它,它应该写成:
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return (Boolean)null;
}
但在尝试拆箱时并不能阻止著名的 NPE 发生;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.