在学习代理模式的时候,编写动态生成代理类.java文件时,用try{}catch(){}捕获异常发现catch(Exception e)报错,得换成catch(Throwable e),然后又查了查两者的区别,在文章最后附上。

这里还是要码一码throws、throw和try catch三者的关系,关键让自己加深印象。

先介绍一下try catch  finally的基本运行流程

    在try语句块中,放入的是你感觉会出现错误的代码,在catch语句块中放入的就是如果try语句块中的代码抛出异常之后所要执行的代码。

try{
  代码1;
  代码2; 
}catch(Exception e){
  代码3; 
}finally{
  代码4;  
}
代码5

1.    正常执行,代码1没有抛出异常,程序的执行顺序就是代码1,代码2,代码4,代码5,。因为没有抛出异常所以跳过了catch语句块。

2.    代码1抛出异常,被catch语句块捕获,而catch语句块中的代码没有抛出新的异常,这样的执行顺序就是代码1,代码3,代码4,代码5。

3.    代码1抛出异常,catch语句块捕获并抛出新的异常,这时候的执行顺序应该为代码1,代码3,代码4,并抛出异常。不执行代码5。

4.    代码1抛出异常,而catch语句块没有与之匹配的异常,那么它的执行顺序就是代码1,代码4.并将异常返回给方法调用者。不执行代码5。

小结:try中如果某行代码抛出异常,不再执行try中其他代码。并向catch语句块抛出异常。catch语句块捕获处理异常,则是为了能够让代码能够顺利运行下去,不会因为try语句块中的异常而终止整个程序。finally语句块则是必定要执行的语句块,不论是否会抛出异常,一定会被执行。若catch语句块与try语句块所抛出的异常无法匹配或抛出新异常,finally之后的代码不执行。

 

throws、throw和try catch解释

1.throw 是语句抛出一个异常,如throw new Exception();他不处理异常,直接抛出异常

1.throws是表明方法抛出异常,需要调用者来处理,如果不想处理就一直向外抛,最后会有jvm来处理;

2.try catch 是自己来捕获别人抛出的异常,然后在catch里面去处理。

使用:

 1.   调用一个会throws exception的方法(在方法定义的时候可以用throws实现)时,需要把这个方法调用放在try里,然后用catch破获这个exception,做相应的处理。

 2.   try....catch是为捕获别人的exception用的,而throw是自己抛出exception让别人去捕获的。

 3.   throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使用,然后再由处理异常的方法捕获。

例如下图

在可能会抛出异常的方法使用throws

将调用该方法的代码放入try中由catch捕获并处理,这里使用printStackTrace()方法,在命令行打印异常信息在程序中出错的位置及原因。

运行结果如下,发现并没有抛出异常(没执行catch),但是调用使用throws的方法一定要放在try中

去除throw代码的注释

再次运行,则会在命令行窗口打印try中第一次抛出异常的位置及原因(try中抛出异常的行后的代码不再执行)

由于抛出的异常和catch的异常匹配,则能继续执行try catch以外的代码。

 

 

 

 附Throwable、 Error、Exception关系

Error类和Exception类的父类都是throwable类,他们的区别是:

Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。

Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

Exception类又分为运行时异常(Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException,编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try。。。catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。

Exception 子类下面的另一部分子类对应于Java程序中的非运行时异常的处理(在下图中将它们直接属于Exception了),这些异常也称为显式异常。它们都是在程序中用语句抛出、并且也是用语句进行捕获的,比如,文件没找到引起的异常、类没找到引起的异常等。 
一些主要子类对应的异常处理功能简要说明如下: 
ArithmeticException——由于除数为0引起的异常; 
ArrayStoreException——由于数组存储空间不够引起的异常; 
ClassCastException—一当把一个对象归为某个类,但实际上此对象并不是由这个类 创建的,也不是其子类创建的,则会引起异常; 
IllegalMonitorStateException——监控器状态出错引起的异常; 
NegativeArraySizeException—一数组长度是负数,则产生异常; 
NullPointerException—一程序试图访问一个空的数组中的元素或访问空的对象中的 方法或变量时产生异常; 
OutofMemoryException——用new语句创建对象时,如系统无法为其分配内存空 间则产生异常; 
SecurityException——由于访问了不应访问的指针,使安全性出问题而引起异常; 
IndexOutOfBoundsExcention——由于数组下标越界或字符串访问越界引起异常; 
IOException——由于文件未找到、未打开或者I/O操作不能进行而引起异常; 
ClassNotFoundException——未找到指定名字的类或接口引起异常; 
CloneNotSupportedException——一程序中的一个对象引用Object类的clone方法,但 此对象并没有连接Cloneable接口,从而引起异常; 
InterruptedException—一当一个线程处于等待状态时,另一个线程中断此线程,从 而引起异常,有关线程的内容,将在下一章讲述; 
NoSuchMethodException一所调用的方法未找到,引起异常; 
Illega1AccessExcePtion—一试图访问一个非public方法; 
StringIndexOutOfBoundsException——访问字符串序号越界,引起异常; 
ArrayIdexOutOfBoundsException—一访问数组元素下标越界,引起异常; 
NumberFormatException——字符的UTF代码数据格式有错引起异常; 
IllegalThreadException—一线程调用某个方法而所处状态不适当,引起异常; 
FileNotFoundException——未找到指定文件引起异常; 
EOFException——未完成输入操作即遇文件结束引起异常。

 

看到一个比较有意思的关于返回值验证try catch  finally执行顺序的帖子:

https://blog.csdn.net/wangqingbo0829/article/details/52458283为转载位置

/**
 * @author qing
 * 
 *    Try……catch……finally中return的测试
 */
public class TryTest {

    /**
     * 主要方法
     */
    public static void main(String[] args) {
        // 调用 测试方法
        String result = get();
        // 打印 测试方法返回的结果
        System.out.println(result);
    }

    @SuppressWarnings({ "finally", "unused" })
    public static String get(){
        int value = 0;
        try {
            System.out.println("try……");
            
            //等式1/0 :分母为0 的明显错误          ——制造错误(用于抛异常)
            int result = 1 / value;
            
            return "111";
            
        } catch (Exception e) {
            System.out.println("catch……");
            return "444";
        } finally {
            System.out.println("finally……");
            return "333";
        }
        
//        return "222";
    }

运行结果:

 

经过测试:

(1)在通过编译器的检查后,如果finally中有return,则以finally中的return为准,其他的都将失效,return之前的代码都有效。

(2)第37行的return “222” 于catch、finally中的任何一个return互斥。也就是说,在catch、finally中其中一个地方存在return,编译器就能检查,已符合方法的返回要求。

(3)catch和finally中,可同时存在return,编译能通过。但程序以finally中的return “333”为准,不会理睬catch中的return “444”,catch中return之前的代码仍然生效。

示例2.     (这种情况就比较好理解了)

         程序中try内部没有异常的情况下,若有finally,且finally中没有return。若在try中遇到return,则先跳去执行finally中的代码,在回来执行try中return。

package threadproject;

/**
 * @author qing
 * 
 *    Try……catch……finally中return的测试
 */
public class TryTest {

    /**
     * 主要方法
     */
    public static void main(String[] args) {
        // 调用 测试方法
        String result = get();
        // 打印 测试方法返回的结果
        System.out.println(result);
    }

    public static String get(){
        try {
            System.out.println("try……");
            
            return "111";
            
        } catch (Exception e) {
            System.out.println("catch……");
        } finally {
            System.out.println("finally……");
        }
        
        return "222";
    }

}

运行结果为:

 

上面的程序不会执行  try……Catch……finally之外的return,即打印的是“111”,而不打印“222”。

posted on 2018-05-21 12:59  王菜鸟1993  阅读(2217)  评论(0编辑  收藏  举报