本章的第一个例子是:
if(t == null)
throw new NullPointerException();
看起来好像在通报进入一个要领的每个句柄中都必需查抄null(因为不知道挪用者是否已通报了一个有效的句柄),这无疑是相当可骇的。但幸运的是,我们基础不必这样做——它属于Java举办的尺度运行期查抄的一部门。若对一个空句柄发出了挪用,Java会自动发生一个NullPointerException违例。所以上述代码在任何环境下都是多余的。
这个种别里含有一系列违例范例。它们全部由Java自动生成,毋需我们亲自动手把它们包括到本身的违例类型里。最利便的是,通过将它们置入单唯一个名为RuntimeException的基本类下面,它们全部组合到一起。这是一个很好的担任例子:它成立了一系列具有某种共通性的范例,都具有某些共通的特征与行为。另外,我们没须要专门写一个违例类型,指出一个要领大概会“掷”出一个RuntimeException,因为已经假定大概呈现那种环境。由于它们用于指出编程中的错误,所以险些永远不必专门捕捉一个“运行期违例”——RuntimeException——它在默认环境下会自动得处处理惩罚。若必需查抄RuntimeException,我们的代码就会变得相当繁复。在我们本身的包里,可选择“掷”出一部门RuntimeException。
假如不捕捉这些违例,又会呈现什么环境呢?由于编译器并不强制违例类型捕捉它们,所以如果不捕捉的话,一个RuntimeException大概过滤掉我们达到main()要领的所有途径。为体会此时产生的工作,请试试下面这个例子:
//: NeverCaught.java // Ignoring RuntimeExceptions public class NeverCaught { static void f() { throw new RuntimeException("From f()"); } static void g() { f(); } public static void main(String[] args) { g(); } } ///:~
各人已经看到,一个RuntimeException(可能从它担任的任何对象)属于一种非凡环境,因为编译器不要求为这些范例指定违例类型。
输出如下:
java.lang.RuntimeException: From f()
at NeverCaught.f(NeverCaught.java:9)
at NeverCaught.g(NeverCaught.java:12)
at NeverCaught.main(NeverCaught.java:15)
所以谜底就是:假使一个RuntimeException得到达到main()的所有途径,同时不被捕捉,那么当措施退出时,会为谁人违例挪用printStackTrace()。
留意也许能在本身的代码中仅忽略RuntimeException,因为编译器已正确实行了其他所有节制。因为RuntimeException在此时代表一个编程错误:
(1) 一个我们不能捕捉的错误(譬喻,由客户措施员吸收通报给本身要领的一个空句柄)。
(2) 作为一名措施员,一个应在本身的代码中查抄的错误(如ArrayIndexOutOfBoundException,此时应留意数组的巨细)。
可以看出,最好的做法是在这种环境下违例,因为它们有助于措施的调试。
别的一个有趣的处所是,我们不行将Java违例分别为单一用途的东西。简直,它们设计用于节制那些讨厌的运行期错误——由代码节制范畴之外的其他气力发生。可是,它也出格有助于调试某些非凡范例的编程错误,那些是编译器侦测不到的。