返回类型Object的方法中的NullPointerException

时间:2015-01-27 16:22:00

标签: java nullpointerexception

为什么以下抛出NullPointerException? :

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : null;
}

public static void main(String [ ] args) {
    myTest(); 
}

我知道如果我执行以下任一操作,代码将不会抛出NullPointerException:

A)

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : (Object) null;
}

public static void main(String [ ] args) {
    myTest(); 
}

B)

public static Object myTest() { 
    Boolean x = false; 
    Boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : null;
}

public static void main(String [ ] args) {
    myTest(); 
}

此外,如果我完全更改代码并执行以下操作:

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 

    if(x && y) {
        return new Object(); 
    } else if(x) {
        return x; 
    } else if(y) {
        return y;
    } else {
        return null;
    }
}

public static void main(String [ ] args) {
    myTest(); 
}

我猜编译器正在进行某种优化,并以某种方式弄乱了一些东西?我假设它是某种类型的转换问题,但为什么在这种情况下会抛出NullPointerException而不是ClassCastException?任何关于为什么会发生这种情况的信息将不胜感激!

提前致谢

2 个答案:

答案 0 :(得分:6)

如果为可读性添加一些括号:

return (x && y) ? (new Object()) : (x ? x : (y ? y : null));

您可以看到在y ? y : null,编译器将尝试取消装箱null(以便类型匹配),从而导致NPE被抛出。

答案 1 :(得分:1)

(这段代码是不可读的,可能应该避免。)但要实际回答: 如上所述,推理与自动装箱和拆箱以及编译器进行检查有关。它好像你写了boolean b = (Boolean) null,它在运行时会抛出一个NPE。

在示例A中,您明确地将其强制转换为Object,因此没有添加自动装箱。

在示例B中,一切都是对象(boolean是基元,而Boolean是对象),所以再次没有装箱或拆箱。

最后,在示例C中,根本没有取消装箱,而是在返回时将结果装箱。 (if-else分支允许编译器单独检查每个分支,而不是需要计算整个语句的三元运算符,然后为整个语句分配一个类型。这与语句与表达式和很多怪异有关在Java自动装箱和类型检查规则中。)

(如果您尝试使用不兼容的转换,如:(Boolean) 7,或者在运行时,如果您执行以下操作,则会在编译时发生转换问题:

int c = 7;
Object co = (Object) c;
Boolean bco = (Boolean) co;
相关问题