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

运行此命令时:

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?

(实际上,我不知道这是否是“向上投射”,因为我抛出了null)

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

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


答案 1

看起来它不是被视为 一个 ,而是试图自己抛出一个 .nullNullPointerExceptionthrow nullNullPointerException

换句话说,检查其参数是否为非空值,如果为 null,则抛出一个 .throwNullPointerException

JLS 14.18 指定以下行为:

如果表达式的计算正常完成并生成 null 值,则会创建并引发类 NullPointerException 的实例 V',而不是 null。然后,throw 语句突然完成,原因是值为 V' 的 throw。


答案 2

为什么它把它投射到NullPointerException?

根据 JLS 14.18

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

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

你可以抛出类型和因为 是 的有效引用,编译器允许它。ThrowablenullThrowable

这是尼尔·古斯特说的(存档))

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


推荐