关于try-catch、throw、finally在异常时的执行顺序

天我给大家讲解一下java的的错误和异常处理机制以及相关异常的执行顺序问题。如有不足的地方,欢迎批评指正~

1、首相简单介绍一下java中的错误(Error)和异常(Exception)
错误和异常的介绍:
在java.lang软件包中有一个java.lang.Throwable类,这个类是java中所有错误和异常的超类。
在java中错误和异常的继承主要有两个: 分别为Error和Exception 这两个。
Error:是java中所有错误类的父类,就是jvm出现错误,以及系统蹦溃等现象,这些错误没办法通过程序来处理,对于系统错误,一般不需要开发人员处理(也无法处理),比如内存溢出(Out of Memory)和线程死锁等系统问题。所以在程序中需要使用catch来捕捉处理这类的错误或者使用throw来抛出相 关的异常。
Exception: 又可以分为checkedException(编译时异常) 和RuntimeException(运行时异常) 这两种异常,checkedException异常在进行编译的时候就可以知道会不会发生异常,如果不对这些异常进行抛出、捕获的话就不能通过编译,如在使用java的io读取文件的时候,可能会会出现所读取的文件不存在的情况 对于,对于这类编译时的异常必须手动去处理它们(捕获或者抛出)。否则的话是无法正常通过编译器的。而RuntimeException就是运行的时候出现的异常,在之前你是没办法确定是不是会出现异常。这类异常仅仅在程序运行的过程中才会发现。
比如数组下标越界(ArrayIndexOutOfBoundsException),强制转换报错(ClassCastException,一部分),空指针异常(NullPointerException)除数为零(/ by zero) 对于这类运行时的异常是否抛出, 由用户根据自身的情况 决定是否抛出异常。java并不强制要求用户 一定处理。

2、异常处理过程

把会出现异常的程序段放在try中,当抛出异常的时候就会在系统中生成一个异常对象,然后进行查找捕获这个异常,然后进行处理这个异常,处理之后接着执行下面的程序。
出现异常之后如果没有进行捕获处理系统就会直接将这个异常栈的跟踪信息直接打印出来之后就结束这个程序的执行。
对于异常的处理方式有两种分别为:try{}catch{}finally{}和throws下面简单说一下这两者的区别和联系

 请先看下面的例子:
     public class Test{
   public static void main(String[] args){
       Test2 test2 = new Test2();
       try{
          System.out.println("invoke the method begin!");
          test2.method();
          System.out.println("invoke the method end!");
       }catch(Exception e){
          System.out.println("catch Exception!");
       }
   }
}

class Test2{
   public void method() throws Exception{
       System.out.println("method begin!");
       int a = 10;
       int b = 0;
       int c = a/b;
       System.out.println("method end!");
   }
}

很明显,答案出来了:
invoke the method begin!
method begin!
catch Exception!

需要注意throw关键字和throws关键字是有区别的。throw一般用于方法中,抛出用户自定义的异常如 throw new MyException(“用户自定义异常”)。而throws是用在方法名的后面,通知使用该方法的人,当前方法有可能抛出异常。如果简单的理解可以这样看:对于throws可以理解为抛出,抛出给别人,自己不处理。而try{}catch{}finally{}则可以理解为截断,开发者自己处理这个异常。
3、异常处理的执行顺序(针对try{}catch{}finally{}而言)对于try{}catch{}finally{}而言,,它们的执行顺序很简单,如果在try{}中捕获相应的异常,中断当前代码的执行,转而去执行catch{}中的内容,最后去执行finally{}中方法,一般来说finally中的方法都是会被执行的,其中finally中很大程度上用于资源的释放。
下面讲解一些我们java程序员需要注意的地方。
a、finally中的代码总是会执行吗?
答:no,如果一个方法内在执行try{}语句之前就已经return了,那么finally语句指定不会执行了。因为它根本没有进入try语句中如果在一个try语句中调用System.exit(0);方法,那么就会退出当前java虚拟机,那么finally也就没有执行的机会了。
b、finally在return之前执行还是在return之后执行?
答:很多人可能会说在return执行之前执行。我的答案是在return中间执行,是不是很特别,请按下面的例子:

package com.yonyou.test;
class Test{

  public static void main(String[] args) {
      System.out.println(method());
     }
  public static int method(){
      int x=1;
      try{
          return x;
      }catch(Exception e)
      {
          return 0;
      }finally{
          ++x;
      }

  }
    }

请问输出的结果是多少呢?
正确答案是:1
下面我来讲解一下这个程序的执行过程,
首先程序在执行到try{}语句中的return方法后,就会先返回相应的值,并把相应的值存储在一个临时栈中去保存这个结果。这时临时栈中存储的值为1。但是程序不会立刻返回,转而回去执行finally中的方法,++x,在finally执行完后,方法全部执行完,这时会再次调用return方法,注意这时不在是返回值,而是告诉主调程序,被调程序已经执行完了,你可以接着去执行你主程序的其它方法了。但是请注意,此时返回的值还是原来保存在临时栈中的值1。
为了更好的理解这个问题,我们看下面的程序:

package com.yonyou.test;


class Test{

  public static void main(String[] args) {
      System.out.println(method());
     }
  public static int method(){
      try{
          return 1;
      }catch(Exception e)
      {
          return 0;
      }finally{
          return 2;
      }

  }
    }

这时的正确答案又是多少呢?
c、finally方法是必须的吗?
不是,开发者可以根据自身的情况去决定是否使用finally关键字。

猜你喜欢

转载自blog.csdn.net/csdn_duanjiao2016/article/details/78501921