以三宫六院比喻try-catch-finally

try-catch-finally结合体是处理程序中异常抛出的代码块,try-catch-finally有很多属于他们群体的游戏规则,生硬地记忆会容易混淆,这里这样打比方:如果try是皇帝,catch是妃子,finally是皇后,那么:

1)妃子(catch)可以一个或者多个。皇后(finally)只有一个。    
        //try-catch-finally中,可能会抛出多个异常,可以用多个catch去捕捉,但finally始终只有一个。

2)try(皇帝)有了妃子(catch),就可以不管皇后(finally)。
       //try后边可以只有catch,没有finally.

3)但try没有妃子(catch)的日子,可以单独和皇后(finally)在一起。
       //try当然也可以没有catch,只跟着finally.

4)皇帝(try)不能单独一个人生活。
       //try单独出现、后边没有catch和finally是错误的。

5)皇帝(try)一抛异常,那就退朝了,异常后边的事情都不管了。
      //如果try代码块中,一抛出异常,异常后边的代码都不会执行。

6)如果皇帝(try)有什么异常,只有妃子(catch)们兜着,但最后收拾烂滩子的只有皇后(finally)。
       //如果try抛出异常,catch去捕捉,但只要finally存在,一定会执行finally的代码。

7)如果妃子(catch)们顺利捕捉即使不处理,宫内秩序一切恢复正常,该溜鸟的溜鸟,该赏花的赏花。
      //如果catch捕捉到了异常,即使处理代码为空,程序还将执行try-catch-finally块下方的代码。

8)如果皇帝(try)抛出的异常不是妃子们没有能力捕捉到,不执行后边的动作,向他们父母禀报,如果父母不处理,大家都死翘翘。
      //如果抛出的异常没有catch到,那向上抛出,交给调用者处理。如果始终程序没有谁对此异常进行响应,那么程序中止,由main方法最终向用户抛出。这是程序员要极力避免的。

9) 宫里出现了刺客,该抓的抓,该杀的杀。但如果一切结束之后,内奸还隐藏在宫中的话,也需要捕捉到底。
     //如果try里抛出的异常被catch到,并处理了。而执行了finally块,但如果finally块里边居然还有异常抛出,必须坚定地在里边再进行try-catch。要不然程序依然会因为异常而暂停执行下去。

下面我们详细讨论下try-catch-finally的使用过程中的疑问,先看这个程序:
public class TestTest {
   static String temp = null;
    public static void main(String[] args) {
       try{
          return; 
       }catch(Exception e){
          temp = "catch";               
       }finally{
          temp = "finally";
       }
       System.out.println(temp);
    }
}
       在这个程序中,如果执行没有输出,直觉上,temp没有赋值。使我们有理由相信try-catch-finally代码块,在try已经return的情况下,finally将不会被执行。事实上是finally是执行了,没有输出是因为return是main方法的return,直接返回的话,是已经退出了JVM,所以System.out没有被执行到。只要有finally,语法上正确的语句,天打雷劈也会去执行finally的代码体的,无论try处还是catch处出现了多少个return语句。不过仔细一想,话好象说过了。如果在try代码块和catch代码块里边,执行到exit()这样的语句或者抛出了error这种致命错误,finally也是不会执行。

       如果catch块中包括多个异常类,这些异常类的匹配原则是什么?接catch块中异常类的排列顺序,寻找第一个能够匹配(也就是做出的异常对象是catch块的异常类,或是属于catch块中异常类的子类),如果你图省事在第一顺位就安排最牛的Exception守着,后边的小异常放在后边,编译器不干了,提示:Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception。

     程序抛出了异常,但在方法体内就被成功捕获,程序可以恢复正常执行。如果但在脱离try-catch-finally代码块时,还是必须执行finally语句;如果程序抛出,本地没有解决掉,向上抛出throws Exception,那么如果这个异常上层没有解决,程序也无法执行下去,如果调用返回已经被上层捕获并处理,程序继续。同样,即使上层没有处理掉此异常,finally还是会执行它的代码体。如下程序所示:

public class P204 {
   public static void main(String[] args) {
      int k=0;
      try{
         int i=5/k;
      }catch(ArithmeticException e){     //这里被捕捉之后,后边的catch只是摆着看看的。
         System.out.print("1");
      }catch(RuntimeException e){
         System.out.print("2");
         return;
      }catch(Exception e){
         System.out.print("3");
      }finally{
         System.out.print("4");      //无论出现什么情况,此句一定会执行
      }
      System.out.print("5");
   }
}

程序输出:145

      在方法覆盖时,子类方法抛出的异常类对象,要么是父类抛出异常的子集,要么是你类抛出的子类对象,反正,不能越权越界抛出。

class AA{
   public void f() throws Exception{}
}
class BB extends AA{
   public void f() throws InterruptedException{}
}

或者:

class AA{
   public void f() throws InterruptedException,ArithmeticException{}
}
class BB extends AA{
   public void f() throws InterruptedException{}
}

     声明自己抛出特定异常类的方法 可以抛出该异常类的任何子类实例。比如我声明我要抛出一堆钱,如果我抛出硬币,1块,10块,都可以。这句话的理解,还是看下边的程序:

public static void main(String[] args) throws ArithmeticException {
      try {
          f();
      } catch (Exception e) {
         throw new ArithmeticException();   //ArithmeticException是方法抛出异常类子类
      }
   }
   
   public static void f()throws Exception{ //这个方法抛出一个异常类对象
      throw new Exception();
   }
}

       最后,还简单提一下Error,它是系统错误,不需要被捕捉,但它可以被捕捉,如下例:

public class Gotcha {
    public static void main(String[] args) {
      try{
      new Gotcha().go();
      }
      catch(Error e){     //这里装腔作势捕捉一下的目的,实际价值是在于真的出错了的情况下,做些小弥补。输出一点信息。
         System.out.println(e);
      }
   }
    void go(){   //一个不负责任的递归,肯定会导致StackOverflowError。
       go();
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值