Java 异常 【 try catch 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就可以明白了。

猜你喜欢

转载自blog.csdn.net/hexiaoli666/article/details/82768615