运行时:
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
将永远是假的。这根本不是真的。
答案 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
类型的对象,因为null
是Throwable
的有效引用,编译器允许它。
虽然可以为每个引用类型赋值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,你可以抛出它。
*排除基本类型。