首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么在这种情况下,为原语返回null会起作用?

为什么在这种情况下,为原语返回null会起作用?
EN

Stack Overflow用户
提问于 2012-11-29 20:34:18
回答 3查看 1.8K关注 0票数 18

这段丑陋的代码可以编译,但如果为s == null,则抛出NPE

代码语言:javascript
复制
public static boolean isNullOrEmpty(String s)
{
    return s != null ? s.isEmpty() : null;
}

虽然这不是(如预期的):

代码语言:javascript
复制
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).的结果

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-29 20:36:47

第一个有一个三元运算符,其结果类型为Boolean。NPE正在将null转换为boolean

它实际上是这样的:

代码语言:javascript
复制
Boolean temp = s != null ? s.isEmpty() : null; //no problems here
return temp; //crash when temp==null

第二个试图返回错误的类型(对象而不是原始类型)-因此无法编译。

票数 16
EN

Stack Overflow用户

发布于 2012-11-29 20:49:13

类似于Tricky Ternary Operator in JAVA

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

Boxing Conversion

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

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

代码语言:javascript
复制
public static boolean isNullOrEmpty(String s)
    {
        return s != null ? null : null;
    }

这段代码不能编译

JLS for Conditional Operator

票数 0
EN

Stack Overflow用户

发布于 2012-11-29 21:44:12

三元运算符需要为两个操作数找出最合适的返回类型。

因此,它允许对返回类型进行一些“润色”。

如您的第一个代码片段所示:

代码语言:javascript
复制
public static boolean isNullOrEmpty(String s)
{
    return s != null ? s.isEmpty() : null;
}

s.empty()返回原语boolean,而第三个操作数返回null。所以最具体的常见返回类型是Boolean。编译器作业类似于将该行替换为:

代码语言:javascript
复制
return s != null ? s.isEmpty() : (Boolean)null; 

返回类型方法需要一个boolean原语,所以编译器会说:“酷,我只需要拆开我的结果!”不幸的是,null并不是不可装箱的,它会导致一个丑陋的NPE。

使用您的第二个代码片段:

代码语言:javascript
复制
public static boolean isNullOrEmpty(String s)
{
    if(s != null)
        return s.isEmpty();
    else
        return null;
}

由于编译器不会链接这段代码中的两个返回语句,因此不会对预返回类型进行额外的“润色”。=>对它来说可能是一项太难的工作。

因此,在这种情况下,由于nullBoolean没有关联,因此代码甚至不编译是合乎逻辑的!因此,不会发生任何类型的强制转换。

要编译它,应将其编写为:

代码语言:javascript
复制
public static boolean isNullOrEmpty(String s)
    {
        if(s != null)
            return s.isEmpty();
        else
            return (Boolean)null;
    }

但不能防止在尝试取消装箱时发生著名的NPE ;)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13625956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档