记录一些关于try-catch-finally的使用:java
1,try{}中若是没有发生异常,catch{}不会执行;app
try{}中若是发生异常,catch{}执行;
不管try{}是否发生异常,finally{}都会执行。this
public class TestFinally { public static void main(String[] args) { TestFinally testFinally = new TestFinally(); testFinally.tryCauseExceptionMethod(); System.out.println("========================"); testFinally.tryNotCauseExceptionMethod(); } private void tryCauseExceptionMethod(){ try{ System.out.println("try start"); int a = 1 / 0; System.out.println("try end"); }catch(Exception e){ System.out.println("catch"); }finally{ System.out.println("finally"); } } private void tryNotCauseExceptionMethod(){ try{ System.out.println("try"); }catch(Exception e){ System.out.println("catch"); }finally{ System.out.println("finally"); } } }
控制台输出:线程
try start catch finally ======================== try finally
2,子类异常不会捕获父类异常。父类异常能够捕获子类异常。code
try { int a = 1 / 0; } catch (MyFirstException e) { System.out.println("fist"); } class MyFirstException extends ArithmeticException{}
以上代码没法捕获异常。对象
3,try、catch、finally中均可以抛出异常,无论是编译器异常仍是运行期异常。继承
若是try中抛出的异常能够被catch捕获,则try中抛出的该异常永远不会被方法调用者捕获。
若是catch中抛出了异常,catch的异常会正常抛出并打印,方法调用者能够捕获catch抛出的该异常。线程能够正常执行。
若是finally中抛出异常,则至关于整个try-catch-finally抛出了异常。内存
public class TestMCatch { public static void main(String[] args) { TestMCatch testCatch = new TestMCatch(); try { testCatch.myCatch(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("cath the method throw"); } System.out.println("even exception happend, the thread still excute"); } private void myCatch() throws FileNotFoundException{ try { throw new FileNotFoundException("try throw exception"); } catch (Exception e) { System.out.println("catch try throw, msg: " + e.getMessage()); throw new FileNotFoundException("catch throw exception"); } } }
控制台输出:get
catch try throw, msg: try throw exception cath the method throw even exception happend, the thread still excute java.io.FileNotFoundException: catch throw exception at cn.testException.TestMCatch.myCatch(TestMCatch.java:30) at cn.testException.TestMCatch.main(TestMCatch.java:15)
4,多个catch{}中,catch是有顺序关系的,且只能被捕获一次。编译器
若是异常具备继承关系,则子类不能出如今父类后,不然编译器不经过。
若是catch的异常彼此意见不具备继承关系,则按照顺序,先匹配的先执行。
(因为java中只能是单继承,因此全部catch中最近接异常的catch会被执行)
try { int a = 1 / 0; } catch (Exception e) { e.printStackTrace(); } catch (ArithmeticExceptione) { e.printStackTrace(); }
以上代码编译不经过。
try { int a = 1 / 0; } catch (ArithmeticException e) { System.out.println("the ArithmeticException catch");; } catch (Exception e) { System.out.println("the Exception catch");; }
控制台输出:
the ArithmeticException catch
5,catch中捕获到异常后,可能再次throw,而且能够把当前的Exception做为构造参数传递,方法调用者捕获后,e.printStackTrace(),控制台会有Caused by 产生。
public class TestReturn { public static void main(String[] args) { TestReturn testReturn = new TestReturn(); try { int a = testReturn.testReturnMethod(); System.out.println(a); } catch (Exception e) { e.printStackTrace(); } } private int testReturnMethod(){ int a = 1; try { a = 1 / 0; return a; } catch (Exception e) { a = 9; throw new RuntimeException(e); } finally { a = 11; } } }
控制台输出:
java.lang.RuntimeException: java.lang.ArithmeticException: / by zero at cn.testException.TestReturn.testReturnMethod(TestReturn.java:26) at cn.testException.TestReturn.main(TestReturn.java:12) Caused by: java.lang.ArithmeticException: / by zero at cn.testException.TestReturn.testReturnMethod(TestReturn.java:22) ... 1 more
6,try-catch-finally与return结合的状况,稍微复杂一些。
首先,方法中常常return的数据分为3类:1.基础数据类型;2.基础数据类型对应的包装类以及String这样的JDK中原生支持的final类;3.其余的普通的POJO类。
为何要分为这3类呢?1.对于基础类型数据,在Java中调用的数据传递是值传递;2.对于Object类型,在Java中调用的数据传递是引用传递,传递的是内存空间的地址值。
那为何还要分为final和非final呢?由于final类的实例对象的地址值是不可更改的。好比:
Integer a = 0; // 堆空间中开辟一块空间,并把new Integer(0)的引用赋给a Integer a = 1; // 堆空间中开辟一块空间,并把new Integer(1)的引用赋给a,原来的new Integer(0)的空间等待被回收
正是由于Integer是final类的,它的改变是须要改变引用地址的。
但是这根本文讨论的try-catch-finally有关系吗?还真有。
6.1,若是finally中有return,则renturn的是finally中的数据。
public static void main(String[] args) { TestReturn testReturn = new TestReturn(); System.out.println(testReturn.testReturnMethod()); } private int testReturnMethod(){ int a = 1; try { a = 10; return a; } catch (Exception e) { a--; return a; } finally { a++; return a; } }
控制台输出: 11
6.2,若是finally中没有return
6.2.1,若是try中有return,return的是基本数据类型,则finally中的修改不会对原return值改变。
public static void main(String[] args) { TestReturn testReturn = new TestReturn(); System.out.println(testReturn.testReturnMethod()); } private int testReturnMethod(){ int a = 1; try { a = 10; return a; } catch (Exception e) { a--; return a; } finally { a++; } }
控制台输出: 10
6.2.2,若是try中有return,return的是基本数据类型的包装类以及String这样的JDK中原生支持的final类,则finally中的修改不会原return值改变。
public static void main(String[] args) { TestReturn testReturn = new TestReturn(); System.out.println(testReturn.testReturnMethod()); } private String testReturnMethod(){ String a = "a"; try { a = "b"; return a; } catch (Exception e) { a = "c"; return a; } finally { a = "d"; } }
控制台输出: b
6.2.3,若是try中有return,return的是普通的POJO类型,这finally对该POJO的修改会影响原return的值。
public class TestReturn { public static void main(String[] args) { TestReturn testReturn = new TestReturn(); User u = new User("lily"); System.out.println(testReturn.testReturnMethod(u).getName()); } private User testReturnMethod(User u){ try { u.setName("try"); return u; } catch (Exception e) { return u; } finally { u.setName("finally"); } } } class User { private String name; public User(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
控制台输出:finally
6.3,总结:try中的retrun拿到最终要return的值,而后进入finally执行。只要finally中没有return,不管finally如何更改,最终要return的值是不会变的(要么是基础数据类型的值,要么是内存空间的地址值)。若是有兴趣反编译的话,能够验证。