异常详细学习

Posted elvin-j-x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异常详细学习相关的知识,希望对你有一定的参考价值。

异常的概念

异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是:

  • 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

注意:异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.

异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable ,其下有两个子类:java.lang.Errorjava.lang.Exception ,平常所说的异常指java.lang.Exception
技术图片

Throwable体系:

  • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。

  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。

 

Throwable中的常用方法:

1 public void printStackTrace()://打印异常的详细信息。
2 //包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用 printStackTrace            
3 
4 public String getMessage()://获取发生异常的原因。
5 //提示给用户的时候,就提示错误原因。
6 
7 public String toString()://获取异常的类型和异常描述信息。
8 //出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。

出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。

技术图片

异常分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?

编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)
技术图片

异常的产生过程解析

 

先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生的过程。

 1 package _1异常和线程._2异常产生过程的解析;
 2 
 3 /**
 4  * @Author Admin
 5  * @Classname DemoException
 6  * @Package _1异常和线程._2异常产生过程的解析
 7  * @GreatDate 2020/04/23 08:43:56
 8  * @Description TODO 异常产生过程解析
 9  */
10 public class DemoException {
11     public static void main(String[] args) {
12         //创建int类型数组,并赋值
13         int[] arr = {1,2,3};
14         int e = getElement(arr, 3);
15         System.out.println(e);
16     }
17     /*
18         定义一个方法,获取数组指定索引处的元素
19         参数:
20             int[] arr
21             int index
22      */
23     private static int getElement(int[] arr,int index) {
24         int ele = arr[index];
25         return ele;
26     }
27 }

技术图片

异常的处理

Java异常处理的五个关键字try、catch、finally、throw、throws

1、抛出异常throw

在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?

  1. 创建一个异常对象。封装一些提示信息(信息可以自己编写)。

  2. 需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?答:通过关键字throw就可以完成。throw 异常对象。throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

throw关键字作用: 可以使用throw关键字在指定的方法中抛出指定的异常使用格式: throw new xxxException("异常产生的原因");注意: 1、throw关键字必须写在方法的内部 2、throw关键字后new的对象必须是Exception或者Exception的子类对象 3、throw关键字抛出指定的异常对象,我们必须处理这个异常对象; throw关键字后边创建的是RuntimeException或者是 RuntimeException的子类对象,我们可以不处理,默认交给JVM【虚拟机】(打印异常对象,中断程序); throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么try...catch(进行捕获处理),要么使用throws(继续讲问题声明出去)。

2、声明异常throws关键字

准备: Objects非空判断

使用其源吗进行演示throws关键字

还记得我们学习过一个类Objects吗,曾经提到过它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),那么在它的源码中,对对象为null的值进行了抛出异常操作。  public static <T> T requireNonNull(T obj):查看指定引用对象不是null。 查看源码发现这里对为null的进行了抛出异常操作:

1 public static <T> T requireNonNull(T obj) {
2     if (obj == null)
3         throw new NullPointerException();
4     return obj;
5 }

throws关键字使用

throws关键字:异常处理的第一种方式,交给别人处理作用: 当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象 可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别 人处理),最终会交给JVM【虚拟机】处理-->中断程序。

使用格式:

1 修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
2     throw new AAAException("产生异常的原因");
3     throw new BBBException("产生异常的原因");
4         ...
5 }

注意事项 1、throws关键字必须写在方法的声明处【参数列表后,{}大括号前】 2、throws关键字后边声明异常必须是Exception或Exception的子类 3、方法的内部如果抛出多个异常对象,那么throws后边必须也声明多个异常, 如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。 4、调用一个声明抛出异常的方法,我们就必须处理声明的异常, 要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM【虚拟机】 要么捕获异常,即try...catch(自己处理异常)

实例

 1 package _1异常和线程._3异常的处理_关键字._2throws_关键字_异常处理的第一种方式$交给别人处理;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.io.IOException;
 5 
 6 /**
 7  * @Author Admin
 8  * @Classname DemoThrrows
 9  * @Package _1异常和线程._3异常的处理_关键字._2throws_关键字
10  * @GreatDate 2020/04/23 13:49:00
11  * @Description TODO 演示声明异常throws关键字_异常处理的第一种方式$交给别人处理
12  */
13 /*
14     throws关键字:异常处理的第一种方式,交给别人处理
15     作用:
16         当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
17         可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别人处理)
18         最终会交给JVM【虚拟机】处理-->中断程序
19     使用格式:
20         修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
21                 throw new AAAException("产生异常的原因");
22                 throw new BBBException("产生异常的原因");
23                 ...
24         }
25         
26     注意事项:
27         1、throws关键字必须写在方法的声明处【参数列表后,{}大括号前】
28         2、throws关键字后边声明异常必须是Exception或Exception的子类
29         3、方法的内部如果抛出多个异常对象,那么throws后边必须也声明多个异常,
30            如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
31         4、调用一个声明抛出异常的方法,我们就必须处理声明的异常,
32            要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM【虚拟机】
33            要么捕获异常,即try...catch(自己处理异常)
34  */
35 public class DemoThrows {
36 /*
37     public static void main(String[] args) throws FileNotFoundException,IOException {}
38 */
39     public static void main(String[] args) throws IOException {
40         readFile("d:a.tx");
41     }
42     
43     /*
44         定义一个方法,对传递的文件路径进行合法性判断
45         如果不是"c:a.txt",那么我们就抛出"文件找不到异常",告知方法的调用者
46         注意:
47             FileNotFoundException是编译异常,抛出了编译异常,就必须处理这个异常
48             可以使用throws继续声明FileNotFoundException这个异常对象,让方法的调用者处理。
49             
50             原因:
51                 FileNotFoundException extends IOException 该异常对象是子父类关系,
52                 因此抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
53      */
54 /*
55     private static void readFile(String filename) throws FileNotFoundException,IOException{}
56 */
57     private static void readFile(String filename) throws IOException{
58         if (!filename.equals("c:a.txt")) {
59             throw new FileNotFoundException("文件路径不是c:a.txt,文件找不到异常");
60         }
61         /*
62             如果传递的路径,不是.txt结尾
63             那么我们就【抛出IO异常对象,告知方法的调用者"文件的后缀名不对"
64          */
65         if (!filename.equals(".txt")) {
66             throw new IOException("文件的后缀名不对");
67         }
68         System.out.println("路径没有问题,读取文件");
69     }
70 }

 

3、捕获异常try…catch关键字

try...catch:异常处理的第二种处理方方式,自己处理异常语法格式:

 1 try{
 2         //可能产生异常的代码
 3     }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
 4       /* 异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
 5         一般在工作中,会把异常的信息记录到一个日志中
 6        */
 7     }
 8     ...
 9     catch(异常类名 变量名){
10     }

注意事项:

1、try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象2、如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继 续执行try...catch之后的代码语句。3、如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行网try中的代码,继续执行try...catch之后的代码语句。

Throwable类中定义了3方法查看异常信息:

1 public String getMessage()://获取异常的简短描述信息
2 public String toString()://获取异常的类型和异常详细描述信息【字符串】
3 public void printStackTrace()://JVM打印异常对象,默认此方法,打印的异常信息是最全面的(打印异常的跟踪栈信息并输出到控制台)。

实例:

 

 1 package _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理;
 2 
 3 import javax.sound.midi.Soundbank;
 4 import java.io.FileNotFoundException;
 5 import java.io.IOException;
 6 
 7 /**
 8  * @Author Admin
 9  * @Classname DemoTryCatch
10  * @Package _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理
11  * @GreatDate 2020/04/23 19:22:17
12  * @Description TODO 演示捕获异常try_catch关键字_异常处理的第二种方式$自己处理异常
13  */
14 /*
15     try...catch:异常处理的第二种处理方方式,自己处理异常
16     语法格式:
17         try{
18             //可能产生异常的代码
19         }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
20             异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
21             一般在工作中,会把异常的信息记录到一个日志中
22         }
23         ...
24         catch(异常类名 变量名){
25         
26         }
27     注意事项:
28         1、try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
29         2、如果try中产生了异常,那么就会执行catch中的异常处理逻辑,
30            执行完毕catch中的处理逻辑,继续执行try...catch之后的代码语句。
31         3、如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,
32            执行网try中的代码,继续执行ry...catch之后的代码语句。
33  */
34 public class DemoTryCatch {
35     public static void main(String[] args) {
36         try {
37             //可能产生异常的代码
38             readFile("c:a.txt");
39         } catch (IOException e) {
40             //try中抛出什么异常对象,cotch就定义什么异常变量,用来接收这个异常对象
41             //异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
42             // System.out.println("catch -文件路径不是c:a.txt,文件找不到异常");
43             // System.out.println("catch -传递的文件后缀不是.txt");
44             
45             /*
46             Throwable类中定义了3方法查看异常信息:
47                 public String getMessage() :获取异常的简短描述信息
48                 public String toString() :获取异常的类型和异常详细描述信息【字符串】
49                 public void printStackTrace() :
50                 JVM打印异常对象,默认此方法,打印的异常信息是最全面的
51                 (打印异常的跟踪栈信息并输出到控制台)。
52              */
53             System.out.println(e.getMessage());//文件的后缀名不对
54             //System.out.println(e.toString());
55             //重写Object类的toString java.io.IOException:文件的后缀名不对
56             System.out.println(e);
57             //该代码语句等同于System.out.println(e.toString());
58             e.printStackTrace();
59             /*
60                 java.io.IOException: 文件的后缀名不对
61                 at _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种                    方式$自己处理.DemoTryCatch.readFile(DemoTryCatch.java:70)
62                 at _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种                    方式$自己处理.DemoTryCatch.main(DemoTryCatch.java:38)
63 
64              */
65         }
66         System.out.println("后续的代码");
67     }
68     private static void readFile(String filename) throws IOException {
69         if (!filename.equals("c:a.txt")) {
70             throw new FileNotFoundException("文件路径不是c:a.txt,文件找不到异常");
71         }
72         /*
73             如果传递的路径,不是.txt结尾
74             那么我们就【抛出IO异常对象,告知方法的调用者"文件的后缀名不对"
75          */
76         if (!filename.endsWith(".txt")) {
77             throw new IOException("文件的后缀名不对");
78         }
79         System.out.println("路径没有问题,读取文件");
80     }
81 }

 

finally 代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

 

注意:1、finally不能单独使用,必须和try一起使用2、finally一般用于资源释放(资源回收),无论线程是否会出现异常,最后都要资源释放 (多是用于IO流方面)  

 1 语法格式:
 2     try{
 3         //可能产生异常的代码
 4     }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
 5      /* 异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
 6         一般在工作中,会把异常的信息记录到一个日志中
 7       */
 8     }
 9     ...
10     catch(异常类名 变量名){
11     
12     }finally{
13         //无论是否出现异常都会执行
14     }

常的概念

异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是:

  • 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。

注意:异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.

异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable ,其下有两个子类:java.lang.Errorjava.lang.Exception ,平常所说的异常指java.lang.Exception技术图片

Throwable体系:

  • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。

  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。

Throwable中的常用方法:

  • public void printStackTrace():打印异常的详细信息。包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace

  • public String getMessage():获取发生异常的原因。

    提示给用户的时候,就提示错误原因。

  • public String toString():获取异常的类型和异常描述信息。

出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。技术图片

异常分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?

编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)

技术图片

异常的产生过程解析

先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下异常产生的过程。

 package _1异常和线程._2异常产生过程的解析;
 ?
 /**
  * @Author Admin
  * @Classname DemoException
  * @Package _1异常和线程._2异常产生过程的解析
  * @GreatDate 2020/04/23 08:43:56
  * @Description TODO 异常产生过程解析
  */
 public class DemoException {
     public static void main(String[] args) {
         //创建int类型数组,并赋值
         int[] arr = {1,2,3};
         int e = getElement(arr, 3);
         System.out.println(e);
    }
     /*
         定义一个方法,获取数组指定索引处的元素
         参数:
             int[] arr
             int index
      */
     private static int getElement(int[] arr,int index) {
         int ele = arr[index];
         return ele;
    }
 }
 ?

异常的产生过程解析图解:

技术图片

异常的处理

Java异常处理的五个关键字try、catch、finally、throw、throws

1、抛出异常throw

在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?

  1. 创建一个异常对象。封装一些提示信息(信息可以自己编写)。

  2. 需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?答:通过关键字throw就可以完成。throw 异常对象。throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

throw关键字作用: 可以使用throw关键字在指定的方法中抛出指定的异常使用格式: throw new xxxException("异常产生的原因");注意: 1、throw关键字必须写在方法的内部 2、throw关键字后new的对象必须是Exception或者Exception的子类对象 3、throw关键字抛出指定的异常对象,我们必须处理这个异常对象; throw关键字后边创建的是RuntimeException或者是 RuntimeException的子类对象,我们可以不处理,默认交给JVM【虚拟机】(打印异常对象,中断程序); throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么try...catch(进行捕获处理),要么使用throws(继续讲问题声明出去)。

2、声明异常throws关键字

准备: Objects非空判断

使用其源吗进行演示throws关键字

还记得我们学习过一个类Objects吗,曾经提到过它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),那么在它的源码中,对对象为null的值进行了抛出异常操作。public static <T> T requireNonNull(T obj):查看指定引用对象不是null。查看源码发现这里对为null的进行了抛出异常操作:

 public static <T> T requireNonNull(T obj) {
 if (obj == null)
 throw new NullPointerException();
 return obj;
 }

throws关键字使用

throws关键字:异常处理的第一种方式,交给别人处理作用: 当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象 可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别 人处理),最终会交给JVM【虚拟机】处理-->中断程序。

使用格式:

 修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
     throw new AAAException("产生异常的原因");
     throw new BBBException("产生异常的原因");
        ...
 }

注意事项 1、throws关键字必须写在方法的声明处【参数列表后,{}大括号前】 2、throws关键字后边声明异常必须是Exception或Exception的子类 3、方法的内部如果抛出多个异常对象,那么throws后边必须也声明多个异常, 如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。 4、调用一个声明抛出异常的方法,我们就必须处理声明的异常, 要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM【虚拟机】 要么捕获异常,即try...catch(自己处理异常)

实例

 package _1异常和线程._3异常的处理_关键字._2throws_关键字_异常处理的第一种方式$交给别人处理;
 ?
 import java.io.FileNotFoundException;
 import java.io.IOException;
 ?
 /**
  * @Author Admin
  * @Classname DemoThrrows
  * @Package _1异常和线程._3异常的处理_关键字._2throws_关键字
  * @GreatDate 2020/04/23 13:49:00
  * @Description TODO 演示声明异常throws关键字_异常处理的第一种方式$交给别人处理
  */
 /*
     throws关键字:异常处理的第一种方式,交给别人处理
     作用:
         当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
         可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别人处理)
         最终会交给JVM【虚拟机】处理-->中断程序
     使用格式:
         修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
                 throw new AAAException("产生异常的原因");
                 throw new BBBException("产生异常的原因");
                 ...
         }
         
     注意事项:
         1、throws关键字必须写在方法的声明处【参数列表后,{}大括号前】
         2、throws关键字后边声明异常必须是Exception或Exception的子类
         3、方法的内部如果抛出多个异常对象,那么throws后边必须也声明多个异常,
            如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
         4、调用一个声明抛出异常的方法,我们就必须处理声明的异常,
            要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM【虚拟机】
            要么捕获异常,即try...catch(自己处理异常)
  */
 public class DemoThrows {
 /*
     public static void main(String[] args) throws FileNotFoundException,IOException {}
 */
     public static void main(String[] args) throws IOException {
         readFile("d:a.tx");
    }
     
     /*
         定义一个方法,对传递的文件路径进行合法性判断
         如果不是"c:a.txt",那么我们就抛出"文件找不到异常",告知方法的调用者
         注意:
             FileNotFoundException是编译异常,抛出了编译异常,就必须处理这个异常
             可以使用throws继续声明FileNotFoundException这个异常对象,让方法的调用者处理。
             
             原因:
                 FileNotFoundException extends IOException 该异常对象是子父类关系,
                 因此抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
      */
 /*
     private static void readFile(String filename) throws FileNotFoundException,IOException{}
 */
     private static void readFile(String filename) throws IOException{
         if (!filename.equals("c:a.txt")) {
             throw new FileNotFoundException("文件路径不是c:a.txt,文件找不到异常");
        }
         /*
             如果传递的路径,不是.txt结尾
             那么我们就【抛出IO异常对象,告知方法的调用者"文件的后缀名不对"
          */
         if (!filename.equals(".txt")) {
             throw new IOException("文件的后缀名不对");
        }
         System.out.println("路径没有问题,读取文件");
    }
 }

3、捕获异常try…catch关键字

try...catch:异常处理的第二种处理方方式,自己处理异常语法格式:

  try{
         //可能产生异常的代码
    }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
       /* 异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
         一般在工作中,会把异常的信息记录到一个日志中
        */
    }
    ...
     catch(异常类名 变量名){
    }

注意事项:

1、try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象2、如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继 续执行try...catch之后的代码语句。3、如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行网try中的代码,继续执行try...catch之后的代码语句。

Throwable类中定义了3方法查看异常信息:

 public String getMessage():获取异常的简短描述信息
 public String toString():获取异常的类型和异常详细描述信息【字符串】
 public void printStackTrace():JVM打印异常对象,默认此方法,打印的异常信息是最全面的
                (打印异常的跟踪栈信息并输出到控制台)。

实例:

 package _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理;
 ?
 import javax.sound.midi.Soundbank;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 ?
 /**
  * @Author Admin
  * @Classname DemoTryCatch
  * @Package _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理
  * @GreatDate 2020/04/23 19:22:17
  * @Description TODO 演示捕获异常try_catch关键字_异常处理的第二种方式$自己处理异常
  */
 /*
     try...catch:异常处理的第二种处理方方式,自己处理异常
     语法格式:
         try{
             //可能产生异常的代码
         }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
             异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
             一般在工作中,会把异常的信息记录到一个日志中
         }
         ...
         catch(异常类名 变量名){
         
         }
     注意事项:
         1、try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
         2、如果try中产生了异常,那么就会执行catch中的异常处理逻辑,
            执行完毕catch中的处理逻辑,继续执行try...catch之后的代码语句。
         3、如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,
            执行网try中的代码,继续执行ry...catch之后的代码语句。
  */
 public class DemoTryCatch {
     public static void main(String[] args) {
         try {
             //可能产生异常的代码
             readFile("c:a.txt");
        } catch (IOException e) {
             //try中抛出什么异常对象,cotch就定义什么异常变量,用来接收这个异常对象
             //异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
             // System.out.println("catch -文件路径不是c:a.txt,文件找不到异常");
             // System.out.println("catch -传递的文件后缀不是.txt");
             
             /*
             Throwable类中定义了3方法查看异常信息:
                 public String getMessage() :获取异常的简短描述信息
                 public String toString() :获取异常的类型和异常详细描述信息【字符串】
                 public void printStackTrace() :
                 JVM打印异常对象,默认此方法,打印的异常信息是最全面的
                 (打印异常的跟踪栈信息并输出到控制台)。
              */
             System.out.println(e.getMessage());//文件的后缀名不对
             //System.out.println(e.toString());
             //重写Object类的toString java.io.IOException:文件的后缀名不对
             System.out.println(e);
             //该代码语句等同于System.out.println(e.toString());
             e.printStackTrace();
             /*
                 java.io.IOException: 文件的后缀名不对
             at _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理.DemoTryCatch.readFile(DemoTryCatch.java:70)
             at _1异常和线程._3异常的处理_关键字._3try_catch_关键字_异常处理的第二种方式$自己处理.DemoTryCatch.main(DemoTryCatch.java:38)
 ?
              */
        }
         System.out.println("后续的代码");
    }
     private static void readFile(String filename) throws IOException {
         if (!filename.equals("c:a.txt")) {
             throw new FileNotFoundException("文件路径不是c:a.txt,文件找不到异常");
        }
         /*
             如果传递的路径,不是.txt结尾
             那么我们就【抛出IO异常对象,告知方法的调用者"文件的后缀名不对"
          */
         if (!filename.endsWith(".txt")) {
             throw new IOException("文件的后缀名不对");
        }
         System.out.println("路径没有问题,读取文件");
    }
 }
 ?
 ?

 

finally 代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

注意:1、finally不能单独使用,必须和try一起使用2、finally一般用于资源释放(资源回收),无论线程是否会出现异常,最后都要资源释放 (多是用于IO流方面)

 语法格式:
     try{
         //可能产生异常的代码
    }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
      /* 异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
         一般在工作中,会把异常的信息记录到一个日志中
       */
    }
    ...
     catch(异常类名 变量名){
     
    }finally{
         //无论是否出现异常都会执行
    }

实例

 package _1异常和线程._4fianlly代码块;
 ?
 import java.io.FileNotFoundException;
 import java.io.IOException;
 ?
 /**
  * @Author Admin
  * @Classname DemoTryCatchFinally
  * @Package _1异常和线程._4fianlly代码块
  * @GreatDate 2020/04/23 21:32:51
  * @Description TODO 演示try_catch_finally,中finally代码块
  */
 /*
     finally代码块
     语法格式:
         try{
             //可能产生异常的代码
         }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
             异常的处理逻辑,产生异常对象之后,怎么处理异常对象?
             一般在工作中,会把异常的信息记录到一个日志中
         }
         ...
         catch(异常类名 变量名){
         
         }finally{
             //无论是否出现异常都会执行
         }
     注意:
         1、finally不能单独使用,必须和try-catch一起使用
         2、finally一般用于资源释放(资源回收),无论线程是否会出现异常,最后都要资源释放
  (多是用于IO流方面)
  */
 public class DemoTryCatchFinally {
     public static void main(String[] args) {
         try {
             //可能产生异常的代码
             readFile("c:a.xt");
        } catch (IOException e) {
             //异常的处理逻辑
             e.printStackTrace();
        }finally {
             //无论是否出现异常都会执行
             System.out.println("资源释放");
        }
    }
     private static void readFile(String filename) throws IOException {
         if (!filename.equals("c:a.txt")) {
           throw new FileNotFoundException("文件路径不是c:a.txt,文件找不到异常");
        }
         /*
             如果传递的路径,不是.txt结尾
             那么我们就【抛出IO异常对象,告知方法的调用者"文件的后缀名不对"
          */
         if (!filename.endsWith(".txt")) {
             throw new IOException("文件的后缀名不对");
        }
         System.out.println("路径没有问题,读取文件");
    }
 }
 ?

 

异常的注意事项:

1、多异常的捕获处理

多个异常使用捕获又该如何处理?

1、多个异常分别处理2、多个异常一次捕获,多次处理3、多个异常一次捕获,一次处理

 package _1异常和线程._1异常._5异常注意事项._1多异常的捕获处理;
 ?
 import java.util.List;
 ?
 /**
  * @Author Admin
  * @Classname DemoException
  * @Package _1异常和线程._5异常注意事项_多异常的捕获处理
  * @GreatDate 2020/04/24 08:28:45
  * @Description TODO 异常注意事项_多异常的捕获处理演示
  */
 /*
     异常的注意事项
  */
 public class DemoException {
     public static void main(String[] args) {
         /*
             多个异常使用捕获又该如何处理?
               1、多个异常分别处理
               2、多个异常一次捕获,多次处理
               3、多个异常一次捕获,一次处理
          */
         1、多个异常分别处理:分别try-catch
        /* try {
             int[] arr = {1, 2, 3};
             System.out.println(arr[3]);
             //ArrayIndexOutOfBoundsException:3 数组索引越界异常
         } catch (ArrayIndexOutOfBoundsException e) {
             System.out.println(e);
         }
         
         List<Integer> list = null;
         try {
             list = List.of(1, 2, 3);
             System.out.println(list.get(3));
             //IndexOutOfBoundsException: Index 3 out-of-bounds for
             //集合索引越界异常
         } catch (IndexOutOfBoundsException e) {
             System.out.println(e);
         }*/
         
         2、多个异常一次捕获,多次处理,那个先越界就只打印那个异常
         /* 就相当于一条公路,开出从主道路开出了分叉的副路,一次只能从其中一个路口开出,
         永远不可能开出两个路口
          */
         try {
             int[] arr = {1, 2, 3};
             System.out.println(arr[3]);
             //ArrayIndexOutOfBoundsException:3 数组索引越界异常
             
             List<Integer> list = List.of(1, 2, 3);
             System.out.println(list.get(3));
             //IndexOutOfBoundsException: Index 3 out-of-bounds for
             //集合索引越界异常
        } catch (ArrayIndexOutOfBoundsException e) {
             System.out.println(e);
        } catch (IndexOutOfBoundsException e) {
             System.out.println(e);
        }
         System.out.println("----------------------");
         /*
        一个try多个catch注意事项:
         catch里定义的变量,如果有子父类关系,那么子类的异常变量必须写在之前,
         否则就会编译报错
         因为 ArrayIndexOutOfBoundsException extendsIndexOutOfBoundsException
         所以子类异常变量必须在父类异常变量之前
            try {
              int[] arr = {1, 2, 3};
              System.out.println(arr[3]);
              //ArrayIndexOutOfBoundsException:3 数组索引越界异常
         
              List<Integer> list = List.of(1, 2, 3);
              System.out.println(list.get(3));
              //IndexOutOfBoundsException: Index 3 out-of-bounds for
              //集合索引越界异常
              }catch (IndexOutOfBoundsException e) {
                   System.out.println(e);
              } catch (ArrayIndexOutOfBoundsException e) {
                   System.out.println(e);
           }
          */
         
         
         3、多个异常一次捕获,一次处理
      /* try {
             int[] arr = {1, 2, 3};
            // System.out.println(arr[3]);
             //ArrayIndexOutOfBoundsException:3 数组索引越界异常
         
             List<Integer> list = List.of(1, 2, 3);
             System.out.println(list.get(3));
             //IndexOutOfBoundsException: Index 3 out-of-bounds for
             //集合索引越界异常
         }catch (IndexOutOfBoundsException e) {
             System.out.println(e);
         }*/
         
         //运行时异常被抛出可以不处理。即不捕获也不声明抛出。
         //默认交给虚拟机处理,终止程序,什么时候不抛出运行时异常了,在继续执行程序
         int[] arr = {1, 2, 3};
         System.out.println(arr[3]);
         //ArrayIndexOutOfBoundsException:3 数组索引越界异常
         List<Integer> list = List.of(1, 2, 3);
         System.out.println(list.get(3));
         //IndexOutOfBoundsException: Index 3 out-of-bounds for
         System.out.println("继续执行后续代码");
    }
 }

 

2、finally有return语句

如果finally有return语句,永远返这回finally中的结果,避免该情况 [尽量避免在finally代码块中,定义变量]。

 package _1异常和线程._1异常._5异常注意事项._2finally有return语句;
 ?
 /**
  * @Author Admin
  * @Classname DemoException
  * @Package _1异常和线程._1异常._5异常注意事项._2finally有return语句
  * @GreatDate 2020/04/24 11:00:15
  * @Description TODO 如果finally有return语句,永远返回finally中的结果,避免情况
  */
 /*
     如果finally有return语句,永远返这回finally中的结果,
     避免该情况[尽量避免在finally代码块中,定义变量]。
  */
 public class DemoException {
     public static void main(String[] args) {
         int a = getA();
         System.out.println(a);
     
    }
     
     private static int getA() {
         int a = 0;
         
         try {
             return a;
        } catch (Exception e) {
             e.printStackTrace();
        } finally {
             //一定会执行的代码
             a = 100;
             return a;
             
        }
    }
 }

 

3、子父类异常

1、如果父类抛出了多个异常,子类覆写父类方法时, 抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

2、父类方法没有抛出异常,子类覆写父类该方法时也不可出异常。 此时子类产生该异常,只能捕获处理,不能声明抛出

注意:父类异常是什么样,子类异常就怎么样

 package _1异常和线程._1异常._5异常注意事项._3子父类异常;
 ?
 /**
  * @Author Admin
  * @Classname Fu
  * @Package _1异常和线程._1异常._5异常注意事项._3子父类异常
  * @GreatDate 2020/04/24 12:34:38
  * @Description TODO 子父类异常
  */
 /*子父类异常:
     1、如果父类抛出了多个异常,子类覆写父类方法时,
     抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
     2、父类方法没有抛出异常,子类覆写父类该方法时也不可出异常。
     此时子类产生该异常,只能捕获处理,不能声明抛出
   
    注意:
     父类异常是什么样,子类异常就怎么样
     
  */
 public class Fu {
     public void show01() throws NullPointerException, ClassCastException { }
     
     public void show02() throws IndexOutOfBoundsException{}
     
     public void show03() throws IndexOutOfBoundsException{}
     
     public void show04() throws Exception {}
     
   
     
 }
 ?
 class Zi extends Fu {
     //子类覆写父类方法是,抛出与父类相同的异常
     @Override
     public void show01() throws NullPointerException, ClassCastException {
     
    }
     
     //子类覆写父类方法时,抛出父类异常的子类
     @Override
     public void show02() throws IndexOutOfBoundsException {
     
    }
     //子类覆写父类方法时,不抛出异常
     @Override
     public void show03(){}
     
     /*@Override
     public void show04() {
         //父类方法没有抛出异常,子类覆写父类该方法时也不可出异常。
     }*/
     
     //此时子类产生该异常,只能捕获处理,不能声明抛出
     @Override
     public void show04() /*错误:throws Exception */{
         try {
             throw new Exception("编译期异常");
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
 }

 

自定义异常类

自定义异常类: Java中提供的异常类,不够我们使用,需要自定义以下异常类语法格式:

    public class xxxException extends Exception或者RuntimeException{
         //1、添加一个空参数的构造方法
         //2、添加一个带异常信息的构造方法
    }

注意:

1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类2.自定义异常类,必须的继承Exception或者RuntimeException 继承 Exception:那么自定义的异常类就是一个编译期异常, 如果方法内部出了编译期异常,就必须处理这个异常, 要么throws;要么try-catch 继承 RuntimeException: 那么自定义的异常类就是一个运行期异常,无需处理, 交给虚拟机处理(中断处理)

 package _1异常和线程._1异常._6自定义异常类;
 ?
 /**
  * @Author Admin
  * @Classname DemoDefineException
  * @Package _1异常和线程._1异常._6自定义异常
  * @GreatDate 2020/04/24 15:09:01
  * @Description TODO 演示自定义注册异常类
  */
 /*
     自定义异常类:
         Java中提供的异常类,不够我们使用,需要自定义以下异常类
         
     语法格式:
         public class xxxException extends Exception或者RuntimeException{
             //1、添加一个空参数的构造方法
             //2、添加一个带异常信息的构造方法
         }
         
     注意:
     1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
     2.自定义异常类,必须的继承Exception或者RuntimeException
         继承 Exception:那么自定义的异常类就是一个编译期异常,
             如果方法内部出了编译期异常,就必须处理这个异常,
             要么throws;要么try-catch
         继承 RuntimeException:
             那么自定义的异常类就是一个运行期异常,无需处理,
             交给虚拟机处理(中断处理)
   
  */
 public class DemoDefineRegisterException extends Exception{
     //1、添加一个空参数的构造方法
     public DemoDefineRegisterException() {
    }
     /*
         2、添加一个带异常信息的构造方法
         查看源码发现,所有的异常类都会有一个带异常信息的构造方法,
         方法内部会调用父类带异常信息的构造方法让父类来处理这个异常信息
      */
     public DemoDefineRegisterException(String message) {
         super(message);
    }
 }
 ?

自定义异常类_练习

要求:我们模拟注册操作,如果用户名已存在则抛出异常并提示:亲,该用户名已经被注册。

分析

1.使用数组保存已经注册过的用户名(数据库)2.使用 Scanner获取用户输入的注册的用户名(前端页面)3.定义一个方法,对用户输入的中注册的用户名进行判断, 3.1.遍历存储已经注册过用户名的数组, 3.2.获取每一个用户名使用获取到的用户名和用户输入的用户名比较 3.3.true:用户名已经存在,抛出 RegisterException异常, 告知用户“亲,该用户名已经被注册"; 3.4.false:继续遍历比较如果循环结束了,还没有找到重复的用户名, 提示用户“恭喜您,注册成功!;

自定义异常类

 package _1异常和线程._1异常._6自定义异常类.自定义异常类_练习;
 ?
 /**
  * @Author Admin
  * @Classname DemoDefineException
  * @Package _1异常和线程._1异常._6自定义异常
  * @GreatDate 2020/04/24 15:09:01
  * @Description TODO 演示自定义注册异常类
  */
 /*
     自定义异常类:
         Java中提供的异常类,不够我们使用,需要自定义以下异常类
         
     语法格式:
         public class xxxException extends Exception或者RuntimeException{
             //1、添加一个空参数的构造方法
             //2、添加一个带异常信息的构造方法
         }
         
     注意:
     1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
     2.自定义异常类,必须的继承Exception或者RuntimeException
         继承 Exception:那么自定义的异常类就是一个编译期异常,
             如果方法内部出了编译期异常,就必须处理这个异常,
             要么throws;要么try-catch
         继承 RuntimeException:
             那么自定义的异常类就是一个运行期异常,无需处理,
             交给虚拟机处理(中断处理)
   
  */
 public class RegisterException extends Exception /*或者RuntimeException*/ {
     //1、添加一个空参数的构造方法
     public RegisterException() {
    }
     
     /*
         2、添加一个带异常信息的构造方法
         查看源码发现,所有的异常类都会有一个带异常信息的构造方法,
         方法内部会调用父类带异常信息的构造方法让父类来处理这个异常信息
      */
     public RegisterException(String message) {
         super(message);
    }
 }

测试类1:

 package _1异常和线程._1异常._6自定义异常类.自定义异常类_练习;
 ?
 import java.util.Scanner;
 ?
 /**
  * @Author Admin
  * @Classname DemoRegisterExceptionPractice
  * @Package _1异常和线程._1异常._6自定义异常类
  * @GreatDate 2020/04/24 16:44:40
  * @Description TODO 自定义异常类练习
  */
 /*
     要求:我们模拟注册操作,如果用户名已存在则抛出异常并提示:亲,该用户名已经被注册。
     分析:
     1.使用数组保存已经注册过的用户名(数据库)
     2.使用 Scanner获取用户输入的注册的用户名(前端页面)
     3.定义一个方法,对用户输入的中注册的用户名进行判断,
       3.1.遍历存储已经注册过用户名的数组,
       3.2.获取每一个用户名使用获取到的用户名和用户输入的用户名比较
         3.3.true:用户名已经存在,抛出 RegisterException异常,
               告知用户“亲,该用户名已经被注册";
         3.4.false:继续遍历比较如果循环结束了,还没有找到重复的用户名,
                提示用户“恭喜您,注册成功!;
  */
 public class DemoRegisterExceptionPractice01 {
     static String[] usernames = {"张三", "李四", "王五"};
     
     public static void main(String[] args) throws RegisterException {
         //2.使用 Scanner获取用户输入的注册的用户名(前端页面)
         Scanner sc = new Scanner(System.in);
         System.out.println("请输入您要注册的用户名:");
         String username = sc.next();
         checkUsername(username);
         
    }
     
     //3.定义一个方法,对用户输入的中注册的用户名进行判断,
     private static void checkUsername(String username) throws RegisterException {
         //3.1.遍历存储已经注册过用户名的数组,
         for (String name : usernames) {
             //3.2.获取每一个用户名使用获取到的用户名和用户输入的用户名比较
             if (name.equals(username)) {
                 /*
                      3.3.true:用户名已经存在,抛出 RegisterException异常,
                                告知用户“亲,该用户名已经被注册";
                  */
                 throw new RegisterException("亲,该用户名已经被注册");
                 //抛出运行期异常,无需处理,交给JVM处理,中断处理
            }
        }
         /*
             3.4.false:继续遍历比较如果循环结束了,还没有找到重复的用户名,
                提示用户"恭喜您,注册成功!"
          */
         System.out.println("恭喜您,注册成功!");
    }
 }
 ?

测试类2:

 package _1异常和线程._1异常._6自定义异常类.自定义异常类_练习;
 ?
 import _1异常和线程._1异常._6自定义异常类.自定义异常类_练习.RegisterException;
 ?
 import java.util.Scanner;
 ?
 /**
  * @Author Admin
  * @Classname DemoRegisterExceptionPractice
  * @Package _1异常和线程._1异常._6自定义异常类
  * @GreatDate 2020/04/24 16:44:40
  * @Description TODO 自定义异常类练习
  */
 /*
     要求:我们模拟注册操作,如果用户名已存在则抛出异常并提示:亲,该用户名已经被注册。
     分析:
     1.使用数组保存已经注册过的用户名(数据库)
     2.使用 Scanner获取用户输入的注册的用户名(前端页面)
     3.定义一个方法,对用户输入的中注册的用户名进行判断,
       3.1.遍历存储已经注册过用户名的数组,
       3.2.获取每一个用户名使用获取到的用户名和用户输入的用户名比较
         3.3.true:用户名已经存在,抛出 RegisterException异常,
               告知用户“亲,该用户名已经被注册";
         3.4.false:继续遍历比较如果循环结束了,还没有找到重复的用户名,
                提示用户“恭喜您,注册成功!;
  */
 public class DemoRegisterExceptionPractice00 {
     static String[] usernames = {"张三","李四","王五"};
     public static void main(String[] args){
         //2.使用 Scanner获取用户输入的注册的用户名(前端页面)
         Scanner sc = new Scanner(System.in);
         System.out.println("请输入您要注册的用户名:");
         String username = sc.next();
         checkUsername(username);
     
    }
     //3.定义一个方法,对用户输入的中注册的用户名进行判断,
     private static void checkUsername(String username){
         //3.1.遍历存储已经注册过用户名的数组,
         for (String name : usernames) {
             //3.2.获取每一个用户名使用获取到的用户名和用户输入的用户名比较
             if (name.equals(username)) {
                 /*
                      3.3.true:用户名已经存在,抛出 RegisterException异常,
                           告知用户“亲,该用户名已经被注册";
                  */
                 try {
                     throw new RegisterException("亲,该用户名已经被注册");
                } catch (RegisterException e) {
                     e.printStackTrace();
                     return;//结束方法
                }
            }
        }
         /*
             3.4.false:继续遍历比较如果循环结束了,还没有找到重复的用户名,
                提示用户"恭喜您,注册成功!"
          */
         System.out.println("恭喜您,注册成功!");
    }
 }
 ?

 

以上是关于异常详细学习的主要内容,如果未能解决你的问题,请参考以下文章

vbscript 各种自定义代码片段 - 有关详细信息,请参阅注释

片段中的Android致命异常

java.util.MissingResourceException: Can't find bundle for base name init, locale zh_CN问题的处理(代码片段

mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段

mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段

异常详细学习