当运行这个:

public class WhatTheShoot {

    public static void main(String args[]){
        try {
            throw null;
        } catch (Exception e){
            System.out.println(e instanceof NullPointerException);
            System.out.println(e instanceof FileNotFoundException);
        }
    }
}

答案是:

true  
false

这对我来说是相当惊人的。我本以为这会导致编译时错误。

为什么我可以抛出null在Java中,为什么它向上转换它到一个NullPointerException?

(实际上,我不知道它是否是一个“上置”,因为我抛出null)

除了一个非常非常愚蠢的面试问题(请不要在面试中问这个问题),我找不到任何理由抛出null。也许你想被解雇,但那…我的意思是,为什么有人会抛出null?

有趣的事实IntelliJ IDEA 12告诉我,我的行,einstanceof NullPointerException,将永远是假的。这根本不是真的。


当前回答

bharal……它看起来是javac编译器错误。我认为它是在SE 5中引入的。 Null可以赋给任何引用类型。然而,“null类型”本身并不是引用类型。程序编译它,因为null可以简单地转换为Exception。 此外,throw在声明之后寻找对象引用,因为null可以作为对象引用,它显示结果。

JLS文档中关于throw的描述如下:

“A throw statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the throw completes abruptly for that reason. If evaluation of the Expression completes normally, producing a non-null value V, then the throw statement completes abruptly, the reason being a throw with value V. If evaluation of the Expression completes normally, producing a null value, then an instance V’ of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V’.”

其他回答

用这种方式思考可以更明显地解释为什么这样做是有效的:

try {
    Exception foo = null;
    if(false) {
        foo = new FileNotFoundException();
    } // Oops, forgot to set foo for the true case..
    throw foo;
} catch (Exception e){
    System.out.println(e instanceof NullPointerException);
    System.out.println(e instanceof FileNotFoundException);
}

为什么要向上转换为NullPointerException?

As for JLS 14.18:

A throw statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the throw completes abruptly for that reason. If evaluation of the Expression completes normally, producing a non- null value V, then the throw statement completes abruptly, the reason being a throw with value V. If evaluation of the Expression completes normally, producing a null value, then an instance V’ of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V’.

为什么我可以抛出null在java ?

可以抛出Throwable类型的对象,因为null是Throwable的有效引用,所以编译器允许这样做。

这是Neal Gafter说的(存档)

虽然null可以赋值给每个引用类型,但null类型本身并不是引用类型。我们的意图是从JLS的第三版中删除throw语句中的表达式是引用类型的要求,但这一更改实际上从未出现在发布版本中。因此,这是我在SE 5中介绍的javac编译器错误。

它的行为符合JLS:

如果表达式的求值正常完成,产生空值,则创建NullPointerException类的实例V',并抛出而不是null。

我不确定,但我猜“throw null”;不工作,并且尝试它会导致程序抛出一个异常,而这个异常恰好是(drum roll) NullPointerException…

看起来,并不是null被视为NullPointerException,而是试图抛出null的行为本身会抛出NullPointerException。

换句话说,throw检查其参数是否为非空,如果为空,则抛出NullPointerException。

JLS 14.18指定了这种行为:

如果表达式的求值正常完成,产生空值,则创建NullPointerException类的实例V',并抛出而不是null。throw语句然后突然结束,原因是一个值为V'的throw。