关于异常处理:为什么“throw null”没有在Java中创建编译错误?

Why is “throw null” not creating a compilation error in Java?

1
2
3
4
5
class ThrowNull {
    public static void main(String[] args) {
        throw null;
    }
}

我们知道throw的规则是throw ThrowableInstance;,其中ThrowableInstance必须是Throwable类型的对象或Throwable的子类。

简单类型(如int或char)以及非Throwable类(如String和Object)不能用作异常。 null是一个特殊的Java文字,表示空值。

那么为什么throw null;会在这段代码中编译?


根据语言规范,throw语句定义为:

1
throw Expression

如果Expression计算为null,则抛出NullPointerException。特别,

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.

由于NullPointerException扩展RuntimeException,因此它是未经检查的异常。这可以解释为什么没有报告此构造的编译时错误。


编译器没有检查很多东西,它假设你做了一些它可能不知道的好理由。它试图阻止的是开发人员常犯的错误。

有人可能认为这是一个很好的简写

1
1
2
3
4
5
6
7
Integer i = null;
try {
    i.intValue();
} catch (NullPointerException npe) {
    System.err.println("Caught NPE");
    npe.printStackTrace();
}

1
2
3
4
5
6
try {
    throw null;
} catch (NullPointerException npe) {
    System.err.println("Caught NPE");
    npe.printStackTrace();
}

用Java 6更新38打印

1
2
3
Caught NPE
java.lang.NullPointerException
    at Main.main(Main.java:9)


我认为因为Null可以被转换为任何类型的引用。所以在编译时它没有错,如果你抛出null而不是throwable。


在generel,而不仅仅是扔。任何对象变量都可以赋值为null。所以我们可以看到抛出并不是特例。应该是吗?也许。它一致吗?是。