如果想在方法中抛出异常,像下面这样直接 throw
是不行的。
public void test() { throw new Exception(); }
这时编译器会给我们一个错误:
Error:(101, 13) java: 未报告的异常错误java.lang.Exception; 必须对其进行捕获或声明以便抛出
想要在方法中手动抛出异常,Java编译器给我们提供了两种选择,要么在方法签名中添加 throws
声明:
public void test() throws Exception { throw new Exception(); }
要么用 try-catch
封印:
public void test() { try { throw new Exception(); } catch (Exception e) { e.printStackTrace(); } }
对于第二种方法,除了语法正确外,屁用没有。
在一般情况下,或则只是为了解决未捕获异常错误,第一种方法已经足够。但是偏偏就有这么一种情况。当我们重写一个方法时,想在方法中抛出异常,但是方法签名中又没有 throws
声明。这就要了老命了,简直让人抓狂,大骂傻逼抓娃。
遇到这种情况也不是毫无办法,考虑下面的函数:
public static double sang(double a, double b) { return a / b } public static void main(String/[/] args) { sang(1, 0); }
用1和0去调用上面的 sang
函数,铁定是要抛出异常的。奇怪的是它的方法签名中既没有 throws
声明,也没有 try-catch
封印,冥冥之中似乎透着那么丁点儿希望。
说到这里,如果你对Java异常分类有所了解的话,已经能从中窥探一二了。Java异常全部继承自 Throwable
,又分为 Error
和 Exception
。 Error
是运行时系统内部错误,编写应用程序很少涉及。 Exception
又有两个分支,分别是 RuntimeException
和 CheckedException
,这就是我们常听说的运行时异常和检测异常,而Java编译器强制必须捕获的就是检查异常。
我们在 test
函数中无法直接抛出异常正是因为被抛出的是一个检查异常,而 double
函数抛出的是运行时异常。所以解决方案也就呼之欲出了,只要将异常包装成运行时异常,就能骗过编译器,成功抛出异常了。
public void test() { throw (RuntimeException)new Exception(); }
当然,这里还要求调用 test
的函数能够捕获到运行时异常,否则抛出这个异常也就没有意义了。如果你是自己写函数调用 test
,那当然皆大欢喜,如果第三方代码库,那就只能祝好运了。