如果s == null
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条件运算符? :
[...]
条件表达式的类型确定如下:
[...]
[...]
答案 0 :(得分:16)
第一个有一个trenary运算符,其结果类型为Boolean
。 NPE正在将null
转换为boolean
。
实际上是这样的:
Boolean temp = s != null ? s.isEmpty() : null; //no problems here
return temp; //crash when temp==null
第二个试图返回错误的类型(Object而不是primitive) - 因此无法编译。
答案 1 :(得分:0)
与Tricky Ternary Operator in JAVA类似
三元运算符使用JLS中引用的规则进行自动装箱:
此规则是必要的,因为条件运算符(第15.25节) 将boxing转换应用于其操作数的类型,并使用 导致进一步的计算。
问题在于Java中的Autoboxing。问题是由于第二个操作数不是第三个。
public static boolean isNullOrEmpty(String s)
{
return s != null ? null : null;
}
此代码不会编译
答案 2 :(得分:0)
三元运算符需要为两个操作数找出最合适的返回类型。
因此,它允许对返回类型进行一些“抛光”。
如您的第一个代码段所示:
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;
}
由于编译器未链接此代码中的两个return语句,因此不会对返回前类型进行额外的“抛光”=>对它来说可能太难了。
因此,在这种情况下,由于null
与Boolean
无关,因此代码甚至无法编译是合乎逻辑的!所以,不会发生任何类型的演员。
要编译它,它应该写成:
public static boolean isNullOrEmpty(String s)
{
if(s != null)
return s.isEmpty();
else
return (Boolean)null;
}
但是在尝试拆箱时不会阻止着名的NPE;)