🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### [把“被检查的异常”转换为“不检查的异常”](https://lingcoder.gitee.io/onjava8/#/book/15-Exceptions?id=%e6%8a%8a%e8%a2%ab%e6%a3%80%e6%9f%a5%e7%9a%84%e5%bc%82%e5%b8%b8%e8%bd%ac%e6%8d%a2%e4%b8%ba%e4%b8%8d%e6%a3%80%e6%9f%a5%e7%9a%84%e5%bc%82%e5%b8%b8) 当编写自己使用的简单程序时,从`main()`中抛出异常是很方便的,但这并不总是有用。真正的问题是,当在一个普通方法里调用别的方法时发现:“我不知道该如何处理这个异常,但是不能把它'吞掉'或者打印一些无用的消息。”有了异常链,一个简单的解决办法就出现了。可以通过将一个“被检查的异常”传递给`RuntimeException`的构造器,从而将它包装进`RuntimeException`里,就像这样: ~~~ try { // ... to do something useful } catch(IDontKnowWhatToDoWithThisCheckedException e) { throw new RuntimeException(e); } ~~~ 如果想把“被检查的异常”这种功能“屏蔽”掉的话,这看上去像是一个好办法。不用“吞下”异常,也不必把它放到方法的异常说明里面,而异常链还能保证你不会丢失任何原始异常的信息。 这种技巧给了你一种选择,你可以不写 try-catch 子句和/或异常说明,直接忽略异常,让它自己沿着调用栈往上“冒泡”,同时,还可以用 getCause() 捕获并处理特定的异常,就像这样: ~~~ // exceptions/TurnOffChecking.java // "Turning off" Checked exceptions import java.io.*; class WrapCheckedException { void throwRuntimeException(int type) { try { switch(type) { case 0: throw new FileNotFoundException(); case 1: throw new IOException(); case 2: throw new RuntimeException("Where am I?"); default: return; } } catch(IOException | RuntimeException e) { // Adapt to unchecked: throw new RuntimeException(e); } } } class SomeOtherException extends Exception {} public class TurnOffChecking { public static void main(String[] args) { WrapCheckedException wce = new WrapCheckedException(); // You can call throwRuntimeException() without // a try block, and let RuntimeExceptions // leave the method: wce.throwRuntimeException(3); // Or you can choose to catch exceptions: for(int i = 0; i < 4; i++) try { if(i < 3) wce.throwRuntimeException(i); else throw new SomeOtherException(); } catch(SomeOtherException e) { System.out.println( "SomeOtherException: " + e); } catch(RuntimeException re) { try { throw re.getCause(); } catch(FileNotFoundException e) { System.out.println( "FileNotFoundException: " + e); } catch(IOException e) { System.out.println("IOException: " + e); } catch(Throwable e) { System.out.println("Throwable: " + e); } } } } ~~~ 输出为: ~~~ FileNotFoundException: java.io.FileNotFoundException IOException: java.io.IOException Throwable: java.lang.RuntimeException: Where am I? SomeOtherException: SomeOtherException ~~~ `WrapCheckedException.throwRuntimeException()`包含可生成不同类型异常的代码。这些异常被捕获并包装进`RuntimeException`对象,所以它们成了这些运行时异常的原因("cause")。 在 TurnOfChecking 里,可以不用 try 块就调用 throwRuntimeException(),因为它没有抛出“被检查的异常”。但是,当你准备好去捕获异常的时候,还是可以用 try 块来捕获任何你想捕获的异常的。应该捕获 try 块肯定会抛出的异常,这里就是 SomeOtherException,RuntimeException 要放到最后去捕获。然后把 getCause() 的结果(也就是被包装的那个原始异常)抛出来。这样就把原先的那个异常给提取出来了,然后就可以用它们自己的 catch 子句进行处理。 这种把被检查的异常用`RuntimeException`包装起来的技术,将在本书余下部分使用。另一种解决方案是创建自己的`RuntimeException`的子类。这样的话,异常捕获将不被强制要求,但是任何人都可以在需要的时候捕获这些异常。