异常处理之try-catch;入门级详解基础又全面

异常处理之try-catch

目标

1,明确什么是异常(重点)
2,能辨识出常见异常和含义(熟悉)
3,理解异常产生原理(了解)
4,能够处理异常(重点)
5,能够自定义异常类型(熟悉)

什么是异常

异常就是在程序中导致程序中断的一种指令流。

如何处理异常

异常怎么发生的呢?

我们写的代码通过main入口被JVM虚拟机调用,但JVM按照你写的指令执行时发现了错误,便会以程序中断的方式告诉你写的代码有错误。


异常类型

官方在发展的过程中给所有异常都归了类,以面向的对象的形式把异常告诉你。
例如当JVM发现了bug,便会创建该bug所属类型的对象,然后以对象的形式告诉你是什么形式的错误。也就是说你这个bug在JVM中变成了一个new(异常)对象的操作,对象创建以后会JVM会返回给main方法(体现是代码下面飘红线),如果此时bug没被处理再通过类似返回的操作把该对象又被JVM调用,如果JVM此时发现了创建的异常对象又回到了自己这里以后,就会中断程序,在窗口报错。
那么抛出个疑问,我们如何在该异常对象返回给JVM的过程中把它拦截呢?


捕获异常

捕获异常操作能够拦截异常对象返回给JVM。

捕获异常语法:

try{
    
    
        //有可能发生异常的代码段
}catch(异常类型1 对象名1){
    
    
        //异常处理操作
}catch(异常类型2 对象名2){
    
    
        //异常处理操作
}...
finally{
    
    
        //异常的统一出口
}

异常就会在try代码块中完成处理。
当代码块的异常满足哪个catch语句时,就会进入哪个catch语句中处理。

catch

catch可以省略不写
省略不写的意思就是执行完finally后,有异常不处理直接抛给调用代码的位置。

finally
在进行异常处理之后,在异常处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行finally代码。

finally可以不用写。
一般用于释放内存操作。

什么时候finally不执行?
只有在走finally之前程序强制退出了,才会不执行。
还有一种,在finally之前出现了System.exit(status:0/1/2/3),finally也不会执行。
System.exit(status:0/1/2/3)表示退出虚拟机,0表示正常退出,1/2/3表示非正常退出。

  • GC只能回收内存垃圾。
  • 注意的是:只要我们加了try-catch,即使try-catch没有解决问题,代码也能继续往下走。
public static void main(String[] args){
    
    
    Person p = haha();
    System.out.println(p.age);  //打印结果为多少?
}
public static Person haha(){
    
    
    Person p = new Person();
    try{
    
    
        p.age = 18;
        return p;
    }catch(Exception e){
    
    
        return null;
    }finally{
    
    
        p.age=23;
    }
    
}
static class Person{
    
    
    int age;
}

在这里打印结果为23,不是18;
我们可能以为try执行到return语句,后面就不再执行了。其实真正的逻辑是执行到return语句后、将要返回p之前,程序会把finally走一遍,最后返回p,以为finally语句必执行,除非程序强制退出。所以得到的结果是23。


return引用数据类型和基本数据类型的区别

根据上面代码再写一段类似的:

public static void main(String[] args){
    
    
    int a = haha();
    System.out.println(a);  //打印结果为多少?
}
public static int haha(){
    
    
    try{
    
    
        int a = 10;
        return a;
    }catch(Exception e){
    
    
        return 0;
    }finally{
    
    
        a = 20;;
    }

此时的打印结果是10,而不是20;
return返回时,内在逻辑是复制了返回者等号右边的数值;

  • 像return p;p是对象名,等号右边是对应堆内存的地址。而finally里面的操作是在堆内存中改变了p的值,地址值不变,p值却改变了。
  • 而return a; a是基本数据类型,等号右边就是数字10,finally里对a重新赋值,但是return返回的依旧是复制的10;但此时a已经是20了。

当一个代码有多个异常时处理方法:

  • 1,写多个catch。一个catch对应解决一个异常。
  • 2,一个catch包含多个异常类型(不常用)
catch(异常类型1|异常类型2|异常类型3 对象名){
    
    
        //异常处理操作
}
  • 3,如果这几个异常都是某个异常的子类,那在catch写上该父类就好了。(多态思想)(常用方式)
catch(RuntimeException 对象名){
    
      //它的子类都能进来
        //异常处理操作
}

异常体现结构

异常指的是Exception,Exception类。
在Java中存在一个类Throwable,它有Exception和Error两种子类。

  • Error:表示的是错误,无法更改代码解决。
  • Exception:表示一般所有程序中的错误,能通过try-catch处理掉。
    • Exception类有很多子类,这些子类能分为两种类别:受检异常和非受检异常
    • 受检异常:必定会抛出bug。
    • 非受检异常:不一定会抛出bug,出现bug可能与输入的数据有关(例如分母不能为零)。

异常的抛出,是抛给调用该方法的位置。

おすすめ

転載: blog.csdn.net/m0_58702068/article/details/120505665