我所理解的JDK异常(二):try-catch-finally的使用
2017-12-31 11:44
459 查看
记录一些关于try-catch-finally的使用:
1,try{}中如果没有发生异常,catch{}不会执行;
try{}中如果发生异常,catch{}执行;
无论try{}是否发生异常,finally{}都会执行。
控制台输出:
2,子类异常不会捕获父类异常。父类异常可以捕获子类异常。
以上代码无法捕获异常。
3,try、catch、finally中都可以抛出异常,不管是编译器异常还是运行期异常。
如果try中抛出的异常可以被catch捕获,则try中抛出的该异常永远不会被方法调用者捕获。
如果catch中抛出了异常,catch的异常会正常抛出并打印,方法调用者可以捕获catch抛出的该异常。线程可以正常执行。
如果finally中抛出异常,则相当于整个try-catch-finally抛出了异常。
控制台输出:
4,多个catch{}中,catch是有顺序关系的,且只能被捕获一次。
如果异常具有继承关系,则子类不能出现在父类后,否则编译器不通过。
如果catch的异常彼此意见不具有继承关系,则按照顺序,先匹配的先执行。
(由于java中只能是单继承,所以所有catch中最近接异常的catch会被执行)
以上代码编译不通过。
控制台输出:
5,catch中捕获到异常后,可能再次throw,并且可以把当前的Exception作为构造参数传递,方法调用者捕获后,e.printStackTrace(),控制台会有Caused by 产生。
控制台输出:
6,try-catch-finally与return结合的情况,稍微复杂一些。
首先,方法中经常return的数据分为3类:1.基础数据类型;2.基础数据类型对应的包装类以及String这样的JDK中原生支持的final类;3.其他的普通的POJO类。
为什么要分为这3类呢?1.对于基础类型数据,在Java中调用的数据传递是值传递;2.对于Object类型,在Java中调用的数据传递是引用传递,传递的是内存空间的地址值。
那为什么还要分为final和非final呢?因为final类的实例对象的地址值是不可更改的。比如:
正是因为Integer是final类的,它的改变是需要改变引用地址的。
可是这根本文讨论的try-catch-finally有关系吗?还真有。
6.1,如果finally中有return,则renturn的是finally中的数据。
控制台输出: 11
6.2,如果finally中没有return
6.2.1,如果try中有return,return的是基本数据类型,则finally中的修改不会对原return值改变。
控制台输出: 10
6.2.2,如果try中有return,return的是基本数据类型的包装类以及String这样的JDK中原生支持的final类,则finally中的修改不会原return值改变。
控制台输出: b
6.2.3,如果try中有return,return的是普通的POJO类型,这finally对该POJO的修改会影响原return的值。
控制台输出:finally
6.3,总结:try中的retrun拿到最终要return的值,然后进入finally执行。只要finally中没有return,无论finally如何更改,最终要return的值是不会变的(要么是基础数据类型的值,要么是内存空间的地址值)。如果有兴趣反编译的话,可以验证。
1,try{}中如果没有发生异常,catch{}不会执行;
try{}中如果发生异常,catch{}执行;
无论try{}是否发生异常,finally{}都会执行。
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,子类异常不会捕获父类异常。父类异常可以捕获子类异常。
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"); } } }
控制台输出:
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的值是不会变的(要么是基础数据类型的值,要么是内存空间的地址值)。如果有兴趣反编译的话,可以验证。
相关文章推荐
- Java异常处理(try、catch、finally使用)
- 异常处理----使用 try…catch…finally 处理异常
- java关于异常处理只使用try-finally而不使用catch
- Java 中使用 try-catch-finally处理异常
- Java中使用try...catch以及try...catch...finally捕获异常
- iOS中@try@catch@finally捕获异常使用
- iOS中@try@catch@finally捕获异常使用
- Java - Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
- Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
- 对try-catch-finally异常处理的最新理解
- C#学习使用try-catch-finally错误处理表达式(续)--定义自己的异常消息类
- C++中的异常捕获与处理:Try、Throw、Catch关键字的理解和使用
- iOS中try-catch-finally捕获异常使用
- 【慕课笔记】第一章 异常与异常处理 第2节 使用try...catch...finally实现异常处理
- JAVA异常处理机制的个人理解(try catch throw finally)
- finally中使用return会吃掉catch中抛出的异常
- Java异常捕获之try-catch-finally-return的执行顺序
- java中异常 try,catch,finally在不同情况下的执行顺序
- IOS开发之--异常处理--使用try 和 catch 来捕获错误。
- 关于try-catch、throw、finally在异常时的执行顺序