Java异常学习总结
一、官方API对此的解释:
1、Throwable:异常和错误的基类,提供了错误堆栈实现等一系列方法。 两个直接子类: Error & Exception
2、两个子类区别:
Error: 程序不应该捕捉的错误,应该交由JVM来处理。一般可能指非常重大的错误。
Exception:程序中应该要捕获的错误。
RuntimeException:运行期异常,是Exception的子类,但勿需捕捉的异常超类
二、各自代码中的表象
Error & RuntimeException:不需要异常处理的,即无try/catch or throws的,编译器认可此种方式;
Exception(排除RuntimeException):编译器强制要求做异常处理的,即必须要 try/catch or throws的;
进一步解释: Exception分为checked Exception & unchecked Exception两种,
unchecked Exception指勿须检查的异常,也即RuntimeException/Error,运行期错误JVM来打理;
checked Exception指必须处理的异常,否则编译器就不让过;
三、为何这样设计?
如上述,Throwable存在2种维度的设计: 1、是否checked 2、 异常级别
是否checked: 表象很明显,编译器会强制检测;
异常级别: 分为 错误和异常,可这个如何来区分呢?我确实很困惑,应该是个人理解的把握了。
四、异常常用关键点知识
1、保留异常源头
异常处理是层级追溯机制,因此异常可被多次抛出,但只要不改变源异常的句柄及其stackTrace,就可一直保留异常源头。
也即简单的throw e(最初的那个异常),异常源头依旧被保留。
2、改变异常源头
如果想改变异常源头,通过抛出一个新异常或在层级机制处理中改变其stackTrace即可。
如在调用方法中e.fillStackTrace() or throw new Excepiton("...")即可定位当前方法为异常源头。
3、自定义异常
一般来说,自定义异常多以checked的为主,也即从Exception继承,实现非常简单,复杂度就看业务需要了,就不多说了。
4、附上部分代码,参照Thinking in java中的实现
public class ThrowableExceptionStudy { // 异常测试 public static void main(String[] args) throws InterruptedException { reThrowTest(); // 异常重新抛出测试(可控制改变源头) rethrowNew(); // 抛出一个新异常测试(改变源头) runtimeExceptionTest(); // 运行期异常测试 errorTest(); // error测试 } /** * 异常重新抛出测试 */ private static void reThrowTest() { try { g(); } catch (Exception e) { // 抛出Exception System.out.println("Caught exception in reThrowTest, e.printStackTrace()"); e.printStackTrace(); } catch (Throwable t) { // 抛出Throwable System.out.println("Caught throwable in reThrowTest, t.printStackTrace()"); t.printStackTrace(); } } /** * 异常源头 */ private static void f() throws Exception { System.out.println("originating the exception in f()"); throw new Exception("thrown from f()"); } /** * 异常重新抛出,不改变异常句柄 * 以两种方式抛出:1、不改变异常源头 2、改变异常源头 */ private static void g() throws Throwable { try { f(); } catch (Exception e) { System.out.println("Inside g(), e.printStackTrace()"); e.printStackTrace(); //throw e; // a: 不改变异常源头 throw e.fillInStackTrace(); // b:改变异常源头, 通过fillInStatckTrace实现 } } /** * 抛出一个新的异常,改变了异常句柄 */ private static void rethrowNew() { try { f(); } catch (Exception e) { System.out.println("Caught in rethrowNew, e.printStackTrace()"); e.printStackTrace(); //throw new NullPointerException("from rethrowNew"); // RuntimeException,编译器自动处理 try { throw new Exception("from rethrowNew"); // 非RuntimeException,必须捕捉 } catch (Exception e1) { e1.printStackTrace(); } } } /** * 运行期异常,勿须捕捉,编译器会自动处理 */ private static void f1() { throw new RuntimeException("From f1()"); } /** * 运行期异常测试 */ private static void runtimeExceptionTest() { try{ f1(); } catch (RuntimeException e){ e.printStackTrace(); } } /** * Error错误 */ private static void error() { throw new Error("custome error,not exception. "); } /** * Error测试 */ private static void errorTest(){ try{ error(); } catch (Error t){ t.printStackTrace(); } } }
运行结果:
originating the exception in f() Inside g(), e.printStackTrace() java.lang.Exception: thrown from f() at com.chq.study.ThrowableExceptionStudy.f(ThrowableExceptionStudy.java:40) at com.chq.study.ThrowableExceptionStudy.g(ThrowableExceptionStudy.java:49) at com.chq.study.ThrowableExceptionStudy.reThrowTest(ThrowableExceptionStudy.java:25) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:14) Caught exception in reThrowTest, e.printStackTrace() java.lang.Exception: thrown from f() at com.chq.study.ThrowableExceptionStudy.g(ThrowableExceptionStudy.java:54) at com.chq.study.ThrowableExceptionStudy.reThrowTest(ThrowableExceptionStudy.java:25) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:14) originating the exception in f() Caught in rethrowNew, e.printStackTrace() java.lang.Exception: thrown from f() at com.chq.study.ThrowableExceptionStudy.f(ThrowableExceptionStudy.java:40) at com.chq.study.ThrowableExceptionStudy.rethrowNew(ThrowableExceptionStudy.java:63) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:15) java.lang.Exception: from rethrowNew at com.chq.study.ThrowableExceptionStudy.rethrowNew(ThrowableExceptionStudy.java:69) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:15) java.lang.RuntimeException: From f1() at com.chq.study.ThrowableExceptionStudy.f1(ThrowableExceptionStudy.java:80) at com.chq.study.ThrowableExceptionStudy.runtimeExceptionTest(ThrowableExceptionStudy.java:88) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:16) java.lang.Error: custome error,not exception. at com.chq.study.ThrowableExceptionStudy.error(ThrowableExceptionStudy.java:98) at com.chq.study.ThrowableExceptionStudy.errorTest(ThrowableExceptionStudy.java:106) at com.chq.study.ThrowableExceptionStudy.main(ThrowableExceptionStudy.java:17)