Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 返回类型对象的方法中的NullPointerException_Java_Nullpointerexception - Fatal编程技术网

Java 返回类型对象的方法中的NullPointerException

Java 返回类型对象的方法中的NullPointerException,java,nullpointerexception,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?:

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)

B)

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

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?任何关于为什么会发生这种情况的信息都将不胜感激


如果您为可读性添加了一些括号,请提前感谢:

return (x && y) ? (new Object()) : (x ? x : (y ? y : null));
你可以在
y中看到这一点?y:null
,编译器将尝试取消装箱
null
(以便类型匹配),导致抛出NPE。

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

在示例A中,您显式地将其强制转换为对象,因此没有添加自动装箱

在示例B中,所有内容都已经是一个对象(布尔值是一个基元,而布尔值是一个对象),所以再次强调,没有装箱或取消装箱

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

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

int c = 7;
Object co = (Object) c;
Boolean bco = (Boolean) co;

它抛出了一个NullPointerException,因为在那一团糟的地方有一个null指针。这是我最初的想法,但我认为它值得一看,所以+1@laune,它确实抛出了一个
NullPointerException
。我认为这应该记录为?@iheani,这不是一个错误的代码。它是有效的。编译器不知为什么出错了不将
null
对象
匹配。要完成:
y:null
的类型由
y
设置,因为左操作数为null。如果添加
(对象)null
,设置类型,防止自动取消装箱到
布尔
,如果添加
布尔y
,则不需要取消装箱,因为
null
适合
布尔
类型。测试后,NPE显然发生在
(x?x:…)
,因为编译器认为
的结果(y?y:null)
必须是一个
布尔值
@njzk2如果我们将
(y?y:null)
视为等同于
returnsnall()
(但我还没有读过它,所以我可能是错的)。@Pshemo:这似乎是完全相同的问题,是的!(有额外的解释)请注意,强制转换显式停止任何类型的自动装箱,并且三元运算符的规则与if-else语句不同。即使没有自动装箱原语的奇怪自动装箱规则,我们也可以看到类似的情况。
return (x && y) ? (new Object()) : (x ? x : (y ? y : null));
int c = 7;
Object co = (Object) c;
Boolean bco = (Boolean) co;