为什么我可以在Java中抛出null?

时间:2013-07-10 17:17:05

标签: java exception-handling nullpointerexception

运行时:

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

这对我来说相当惊人。我原本以为这会造成编译时错误。

为什么我可以在Java中抛出null,为什么要将它转换为NullPointerException?

(实际上,我不知道它是否是“向上”,因为我扔的是空的)

除了一个非常愚蠢的面试问题(请不要在面试中问这个问题)我看不出throw null的任何理由。也许你想被解雇,但那是......我的意思是,为什么其他人throw null

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

7 个答案:

答案 0 :(得分:408)

看起来并不是null被视为NullPointerException,但尝试throw null 本身的行为会引发NullPointerException

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

JLS 14.18 specifies这种行为:

  

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

答案 1 :(得分:95)

为什么要将它向上转换为NullPointerException?

根据JLS 14.18

  

throw语句首先评估Expression。如果表达式的评估由于某种原因突然完成,则抛出因此原因突然完成。如果表达式的评估正常完成,产生非空值V,则throw语句突然完成,原因是值为V的throw。如果表达式的评估正常完成,产生空值,则创建并抛出类NullPointerException的实例V'而不是null。然后throw语句突然完成,原因是值为V'的抛出。

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

您可以抛出Throwable类型的对象,因为nullThrowable的有效引用,编译器允许它。

这就是Neal Gafter says

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

答案 2 :(得分:21)

符合JLS

的行为
  

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

答案 3 :(得分:18)

通过这种方式思考,可以更清楚地了解其工作原理:

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);
}

答案 4 :(得分:13)

不确定,但我猜测"抛出零&#34 ;; 工作,并尝试它会导致程序抛出异常,并且该异常恰好是(鼓滚动)NullPointerException ...

答案 5 :(得分:-3)

bharal ...它看起来像一个javac编译器bug。我认为它是在SE 5中引入的。 Null可以分配给任何引用类型。但是,“null类型”本身不是引用类型。程序编译它,因为null可以简单地转换为Exception。 此外,throw会在声明后查找对象引用,并且null可以作为对象引用,它会显示结果。

关于throw as的JLS文档:

  

“throw语句首先评估Expression。如果评价   由于某种原因,表达式突然完成,然后抛出   因此而突然完成。如果评估表达式   正常完成,产生非空值V,然后抛出   声明突然完成,原因是投掷价值V.   如果Expression的表达式正常完成,则生成null   value,然后创建类NullPointerException的实例V'   并抛出而不是null。然后throw语句完成   突然之间,原因是投掷价值V'。“

答案 6 :(得分:-3)

null 可以转换为任何*,包括异常。就像你的方法签名指定你应该返回一个Exception(或者确实是一个字符串或Person类)一样,你可以返回null,你可以抛出它。

*排除基本类型。