基本异常
是指阻止当前的方法或者作用域继续执行的问题
普通问题:在当前的环境下能够获得足够的信息,总能处理这个错误,但是异常情形无法获得的必要的信息来解决问题
抛出异常:从当前的环境跳出,把问题提交给上一级环境。
首先,就像创建其他对象一样,先使用new在堆上创建异常对象,然后当前的执行路径被终止。并且从当前的环境中弹出对异常对象的引用,这个时候,异常处理机制接管程序,并且寻找一个恰当的位置来继续执行程序(并不是说异常发生,程序就不会继续执行了)
这个恰当的位置就是异常处理程序,它的任务就是将程序从错误状态中恢复回来,要么程序继续执行,要么换一种方式继续执
异常参数
所有的标准异常类都有两个构造器:一个是默认构造器,另一个是接受字符串作为参数
从效果上看throw就像是从方法中返回的,可以将它看成一种不同的返回机制,另外还可以用抛出异常的方式从当前的作用域退出。
try块
如果在方法内部抛出了异常,这个方法就在抛出异常之后就结束了
如果不希望就此结束,可以在方法内部设置一个try块,来捕获异常,因为这个块里尝试各种方法调用(可能产生异常的),是跟在try后面的普通程序代码块:try{}
异常处理程序catch
抛出的异常必须在某个地点得到处理,这里就是异常处理程序,并且对于每个捕获的异常,都得到相应的处理程序
它紧跟在try块后面,用关键字catch表示
终止和恢复
终止模型:一旦异常被抛出,就会终止程序
恢复模型:通常是异常被处理之后,可以继续程序的运行的(catch中不要throw)
创建自定义异常
要自己定义异常,必须从已有的异常类中继承,而且最好选择意思相近的异常类继承
public class InheritingExceptions {public void f() throws SimpleException {System.out.println("Throw SimpleException from f()");throw new SimpleException(); //异常对象引用}public static void main(String[] args) {final InheritingExceptions i = new InheritingExceptions();try {i.f();} catch (SimpleException e) {System.out.println("Caught it");}}}
对异常来说,最重要的就是部分就是类名和错误提示
也可以为自定义异常创建一个带参数的构造器
class MyException extends Exception{public MyException(){}public MyException(String msg){super(msg);}}public class FullConstructor {public static void f() throws MyException {System.out.println("Throwing MyException from f()");throw new MyException();}public static void g() throws MyException {System.out.println("Throwing MyException from g()");throw new MyException("Originated in g()");}public static void main(String[] args) {try {f();} catch (MyException e) {e.printStackTrace();}try {g();} catch (MyException e) {e.printStackTrace();}}}
捕获所有异常
通过只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类Exception,最好将其放在处理程序列表的末尾
栈轨迹
public class WhoCalled {static void f(){try {throw new Exception();} catch (Exception e) {for (StackTraceElement stackTraceElement : e.getStackTrace()) {System.out.println(stackTraceElement.getMethodName());}}}static void g(){f();}static void h(){g();}public static void main(String[] args) {f();System.out.println("------------");g();System.out.println("------------");h();}
重新抛出异常
把刚捕获的异常重新抛出,重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch字句将被忽略。如果只是把当前的异常重新抛出,那么printStackTrace()方法显示的是原来异常抛出点的调用栈信息,而不是重新抛出点的信息
public class ReThrowing {public static void f() throws Exception {System.out.println("originating the exception in f()");throw new Exception("thrown in f()");}public static void g() throws Exception {try {f();} catch (Exception e) {System.out.println("Inside g(),e,printStackTrace()");e.printStackTrace();throw e;}}public static void h() throws Exception {try {f();} catch (Exception e) {System.out.println("Inside h(),e.printStackTrace()");e.printStackTrace();throw (Exception) e.fillInStackTrace(); //调用这个方法就成了异常的新发生地}}public static void main(String[] args) {try {g();} catch (Exception e) {System.out.println("Main,printStackTrace()");e.printStackTrace();}try {h();} catch (Exception e) {System.out.println("Main,printStackTrace()");e.printStackTrace();}}}
class OneException extends Exception{public OneException(String s){super(s);}}class TwoException extends Exception{public TwoException(String s){super(s);}}public class RethrowNew {public static void f() throws OneException {System.out.println("originating the exception in f()");throw new OneException("throw from f()");}public static void main(String[] args) {try {try {f();} catch (OneException e) {System.out.println("Caught in inner try, e.printStackTrac()");e.printStackTrace();throw new TwoException("from inner try");}}catch (TwoException e){System.out.println();e.printStackTrace();}} //组后异常仅仅知道自己来自main(),而且对f()一无所知}
Java标准异常
Throwable这个类可以作为任何异常被抛出的类,它可以分为两种类型
Error:表示编译时和系统错误,一般不需要关心
Exception:是可以被抛出的基本类型,在Java类库,用户方法,或者运行时的故障都可能抛出Exception异常
通常关心的基本类型时Exception
RuntimeException
使用finally进行清理
finally子句总能运行
class ThreeException extends Exception{}public class FinallyWorks {static int i = 0;public static void main(String[] args) {while (true){try{if (i++ == 0){throw new ThreeException();}System.out.println("No exception");}catch (Exception e){System.out.println("Three Exception");}finally { //finally语句总能执行System.out.println("In finally clause");if (i == 2){break;}}}}}
如果异常抛出了但是没有被捕获,就会出现下种情况
public class Switch {private boolean state = false;public boolean read(){return state;}public void on(){state = true;System.out.println(this);}public void off(){state = false;System.out.println(this);}@Overridepublic String toString() {return state ? "on" : "off";}}class OnOffException1 extends Exception{}class OnOffException2 extends Exception{}public class OnOffSwitch {static Switch sw = new Switch();public static void f() throws OnOffException1,OnOffException2{}public static void main(String[] args) {try {sw.on();f();//sw.off(); //注掉发现并没有执行下列catch中任何一个off方法}catch (OnOffException1 e){System.out.println("OneException1");sw.off();}catch (OnOffException2 e){System.out.println("OneException2");sw.off();}}}
此时finally的作用就来了
public class OnOffSwitch {static Switch sw = new Switch();public static void f() throws OnOffException1,OnOffException2{}public static void main(String[] args) {try {sw.on();f();//sw.off();}catch (OnOffException1 e){System.out.println("OneException1");sw.off();}catch (OnOffException2 e){System.out.println("OneException2");sw.off();}finally { //finally子句总可以运行sw.off();}}}
甚至异常没有被当前的异常处理程序捕获的情况下,异常处理机制,也会在跳在更高一层的异常处理程序之前,执行finally子句
class FourException extends Exception{}public class AlwaysFinally {public static void main(String[] args) {System.out.println("first");try {System.out.println("second");try {throw new FourException();}finally {System.out.println("2nd");}}catch (Exception e){System.out.println("3rd");}finally {System.out.println("4th");}}}
在return中使用finally
public class MultipleReturns {public static void f(int i){System.out.println("=====================");try {System.out.println("1");if (i == 1){return;};System.out.println("2");if (i == 2){return;}System.out.println("3");if (i == 3){return;}}finally {System.out.println("Always finally");}}public static void main(String[] args) {for (int i = 1; i < 4; i++) {f(i);}}}
缺憾: 异常丢失
class VeryImportantException extends Exception{@Overridepublic String toString() {return " A very important exception";}}class HomuException extends Exception{@Overridepublic String toString() {return "A trivial exception";}}public class LostMessage {void f() throws VeryImportantException {throw new VeryImportantException();}void g() throws HomuException {throw new HomuException();}public static void main(String[] args) {try {LostMessage lm = new LostMessage();try {lm.f();}finally {lm.g();}}catch (Exception e){System.out.println(e); //VeryImportantException丢失了}}}
