try{}catch{}finally{}、throw、throws关键字

Throwable为顶层父类;

Throwable又派生出Error类和Exception类;

错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。

异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。

 

检查和非检查是对于javac来说的

非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类。javac在编译时,不会提示和发现这样的异常,不要求在程序处理这些异常。

检查异常(checked exception):除了Error 和 RuntimeException的其它异常。javac强制要求程序员为这样的异常做预备处理工作(使用try…catch…finally或者throws)。

1、try…catch…finally语句块

try{
     //try块中放可能发生异常的代码。

     //如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码(如果有的话)。

     //如果发生异常,则尝试去匹配catch块。

    //try块中的局部变量和catch块中的局部变量(包括异常变量),以及finally中的局部变量,他们之间不可共享使用。
}catch(SQLException SQLexception){

    //每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。

    //catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。

    //在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。

    //如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部caller中去匹配异常处理器。

    //如果try中没有发生异常,则所有的catch块将被忽略。

   //一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义

}catch(Exception exception){

 
    //.....


}finally{

    //finally块通常是可选的。

   //无论异常是否发生,异常是否匹配被处理,finally都会执行。

   //一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。             

  //finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。 

}

2、throw

抛出一个异常,一般是在函数代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常


public void  getOffer(String s) {

    if(s.equals("abc")) {

       throw new NumberFormatException();

    }

    if(s.equals("")) {

       throw new Exception("入参 S 不能为空");

    } else {

        System.out.println(s);

    } 
}

3、throws

可能抛出异常的声明  (用在声明方法时,表示该方法可能要抛出异常)

当某个方法可能会抛出某种异常时用于throws 声明可能抛出的异常,然后交给上层调用它的方法程序处理

public class testThrows(){

    public static void function() throws NumberFormatException{ 

        String s = "abc"; 

        System.out.println(Double.parseDouble(s)); 

    } 

    public static void main(String[] args) { 

        try { 

            function(); 

        } catch (NumberFormatException e) { 

            System.err.println("非数据类型不能强制类型转换。"); 

        } 

    }

throw与throws的比较

1、throws出现在方法函数头;而throw出现在函数体。

2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

 

编程习惯:

  1. 在写程序时,对可能会出现异常的部分通常要用try{...}catch{...}去捕捉它并对它进行处理;
  2. 用try{...}catch{...}捕捉了异常之后一定要对在catch{...}中对其进行处理,那怕是最简单的一句输出语句,或栈输入e.printStackTrace();
  3. 如果是捕捉IO输入输出流中的异常,一定要在try{...}catch{...}后加finally{...}把输入输出流关闭
  4. 如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。

4、try,catch,finally 包含return语句时,处理方法如下

1、首先要确定的一点是,不管有木有出现异常,finally块中代码都会执行

2、当try和catch中有return时,finally仍然会执行;

4、finally中最好不要包含return否则返回值不是try或catch中保存的返回值。

5、执行try块,执行到return语句时,先执行return的语句,但是不返回到main 方法,接下来执行finally块,遇到finally块中的return语句,执行,并将值返回到main方法,这里就不会再回去返回try块中计算得到的值

案例如下:

先亮一道面试

public static int func (){

    try{ 

        return 1; 

    }catch (Exception e){ 

        return 2; 

    }finally{ 

        return 3;

    } 
}

下面函数的返回值是什么?

答案是:3

这一题,一定要注意的是finally中的语句一定会执行。所以执行到finally里面的return语句就会return3。而在try中遇到return 2;的时候只是先缓存起来等待finally执行完,然后直接把缓存的数据return出去。所以,一定要记住,finally中的修改语句不会影响到try和catch中return已确定的返回值。但是如果finally中有返回值,就会直接覆盖try,catch语句中的返回值,直接返回。

就上面的黑体字再举一个例子:

public class Demo2 {

    int num = 0;

     public int fun() {

        try {

            return ++num;

        } catch (Exception e) {

            return 2;

        } finally {

            ++num;

        }

    }

    public static void main(String[] args) {

        Demo2 demo2 = new Demo2();

        int a = demo2.fun();

        System.out.println(a);

    }

}

这段代码的输出语句很容易受到上面那段代码的影响,大家可能认为结果是2,然而正确结果是1。正如前面那句黑体字说的,finally语句不会影响到finally中的return语句已经确定的返回值。

那么下面这段代码呢???


public class Demo2 {

     int num = 0; 

    public int fun() {

      try { 

         return ++num;

      } catch (Exception e) {

            return 2; 

      } finally { 

          return ++num; 

    }
 } 
 
 public static void main(String[] args) { 

     Demo2 demo2 = new Demo2();

     int a = demo2.fun(); 

     System.out.println(a);

 } 
}

 

这个结果是2,和上面的又不一样了是吧。这里大家不用犯晕,很容易理解的,就是在try中的return语句是把num变成了1,而finally中就把num又加了一次就变成 2 然后返回了。 其实可以在finally中加一个输出语句输出一下finally就可以明白了。

---------------------------------------------------------------------

Thread.sleep()方法的异常

public static native void sleep(long millis) throws InterruptedException

//在sleep()方法上用throws关键字声明了一个可能发生的异常IntereuptedException

我们在调用这个sleep()方法的时候就需要使用try{}catch{}来处理这个异常或者继续在方法上使用thows关键字声明异常

  • 使用try{}catch{}处理方法如下:

  • 使用throws关键字继续在方法上进行声明异常,这样的话,就需要在调用myObject()的方法里进行异常处理。

关于try catch finally中return返回值的总结:

  • try和catch中同时存在return语句,try{}catch(){}finally{}之外的return就是不可达语句,编译报错
  • finally中存在return语句,try{}catch(){}finally{}之外的return就是不可达语句,编译报错
  • 当finally中有return语句时,始终返回的时finally中的return
  • 当finally中无return语句时,无异常返回try中的return;有异常返回catch中的return。但finally中的语句都是会执行的
  • 如果finally中没有操作try(catch)中要返回的变量值,则返回try(catch)中的return值。如果finally中有操作finally中返回的变量值:当该变量是基本数据类型,则try(catch)中的return值不受finally对该变量操作的影响;当该变量是引用类型,则try返回值回受finally中对该变量操作的影响

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值