为什么我可以在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?
(其实,我不知道这是否是一个“upcast”,因为我扔了null)
除了一个非常愚蠢的面试问题(请别人在面试中提出这个问题),我看不出任何理由throw null
。 也许你想被解雇,但那是…我的意思是,为什么有人会throw null
?
有趣的事实 IntelliJ IDEA 12告诉我,我的行, e instanceof NullPointerException
,将永远是错误的。 这根本不是真的。
它看起来不是null
被视为NullPointerException
,而是试图throw null
的行为本身抛出一个NullPointerException
exception。
换句话说, throw
检查它的参数是否为空,如果是null,则抛出一个NullPointerException
exception。
JLS 14.18 指定了这个行为:
如果对Expression的评估正常完成,则生成一个空值,然后创build类NullPointerException的实例V'并抛出而不是null。 throw语句突然完成,原因是一个值为V'的throw。
为什么它向上抛出NullPointerException?
根据JLS 14.18 :
一个throw语句首先评估expression式。 如果由于某种原因,expression式的评估突然完成,那么抛出就会因为这个原因而突然完成。 如果Expression的求值正常完成,产生一个非空值V,则throw语句突然完成,原因是一个带有值V的throw。 如果对Expression的求值正常完成,产生一个空值,那么一个实例V'类NullPointerException的创build和抛出而不是null。 throw语句突然完成,原因是一个值为V'的throw。
为什么我可以在Java中抛出null?
您可以抛出Throwable
types的对象,由于null
是Throwable
的有效引用,编译器允许它。
这就是Neal Gafter所说的
虽然null可分配给每个引用types,但nulltypes本身不是引用types。 我们的意图是,将throw语句中的expression式作为引用types的要求将从JLS的第三版中删除,但是这种更改实际上并没有真正将其引入到已发布的版本中。 因此,这是我在SE 5中介绍的一个javac编译器错误。
它的行为符合JLS :
如果对Expression的评估正常完成,则生成一个空值,然后创build类NullPointerException的实例V'并抛出而不是null。
以这种方式思考这个问题使得这个工作原理更为明显:
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); }
不知道肯定,但我猜测“扔零”; 不起作用,并尝试它导致程序抛出一个exception,并且该例外碰巧是(鼓滚)NullPointerException …
null可以转换为任何*,包括一个Exception。 就像你可以返回null如果你的方法签名指定你应该返回一个Exception(或者确实是一个string,或Person类),你可以抛出它。
*不包括原始types。
bharal …它看起来是一个javac编译器错误。 我认为它是在SE 5中引入的。空值可以被分配给任何引用types。 但是,“null的types”本身不是一个引用types。 该程序编译它,因为null可以简单地投入到exception。 此外,在声明之后抛出对象引用,因为null可以作为对象引用来显示结果。
JLS文档关于抛出:
“一个throw语句首先评估expression式。 如果由于某种原因,expression式的评估突然完成,那么抛出就会因为这个原因而突然完成。 如果expression式的求值正常完成,产生一个非空值V,则throw语句突然完成,原因是一个带有值V的抛出。如果expression式的求值正常完成,产生一个空值,那么一个实例V'类NullPointerException的创build和抛出而不是null。 throw语句突然完成,原因是一个值为V'的抛出。