为什么在这种情况下,为基元返回 null 会起作用?

2022-09-02 22:06:10

这段丑陋的代码确实可以编译,但如果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 条件运算符 ?:

[...]

条件表达式的类型确定如下:

[...]

  • 如果第二个和第三个操作数之一是基元类型 T,而另一个操作数的类型是将装箱转换 (§5.1.7) 应用于 T 的结果,则条件表达式的类型为 T。

[...]

  • 否则,第二个和第三个操作数分别为 S1 和 S2 类型。设 T1 是将装箱转换应用于 S1 所得到的类型,让 T2 是将装箱转换应用于 S2 所得到的类型。条件表达式的类型是将捕获转换 (§5.1.10) 应用于 lub(T1, T2) (§15.12.2.7) 的结果。

答案 1

一个有一个三元算子,其结果类型为 。NPE 正在将 a 转换为 .Booleannullboolean

它实际上是这样的:

Boolean temp = s != null ? s.isEmpty() : null; //no problems here
return temp; //crash when temp==null

第二种是尝试返回错误的类型(Object而不是基元) - 因此无法编译。


答案 2

类似于JAVA中的棘手三元运算符

三元运算符使用 JLS 中引用的规则执行自动装箱:

拳击转换

此规则是必需的,因为条件运算符 (§15.25) 将装箱转换应用于其操作数的类型,并在进一步的计算中使用结果。

问题在于Java中的自动装箱。问题是由于第二个操作数而不是第三个。

public static boolean isNullOrEmpty(String s)
    {
        return s != null ? null : null;
    }

此代码无法编译

条件运算符的 JLS


推荐