1、异常概念&异常体系

Throwable 类是所有异常exception和错误error的超类,在java.lang 包中
1、Exception 编译期异常,进行编译java程序出现的问题
Exception 的子类,RuntimeException:运行期异常,
上面两种相当于程序的小毛病。把异常处理掉,程序可以继续执行
2、Error:错误, 相当于程序得了无法治愈的毛病,必须修改代码, 程序才能继续执行

Throwable中的常用方法:
1、 public void printStackTrace():打印异常的详细信息。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。
2、 public String getMessage():获取发生异常的原因。
提示给用户的时候,就提示错误原因。
3、 public String toString():获取异常的类型和异常描述信息(不用)。
出现异常,最简单的方式就是把异常的简单类名,拷贝到API中去查。
package exception2;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* created by apple on 2020/6/21
* java.lang.Throwable:类是java语言中 所有错误或异常的超类
*/
public class Demo01Exception {
public static void main(String[] args) /*throws ParseException */{
//Exception 编译期异常 进行编译(写代码) java程序出现的问题
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;//把字符串格式的日期,解析成Date格式的日期
try {
date = sdf.parse("1990-09-09");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
System.out.println("上面报错了,但是这句还能执行");
//运行期异常
int[] arr ={1,3,5};
// System.out.println(arr[5]); //ArrayIndexOutOfBoundsException,索引越界异常,运行期出现的异常
try {
//可能会出现异常的代码
System.out.println(arr[5]);
}catch(Exception e){
//异常的处理逻辑
e.getStackTrace();
System.out.println(e) //ArrayIndexOutOfBoundsException
}
System.out.println("上面报错了,但是这句还能执行");
//Error 错误
int[] arr1 = new int[1024*1024*1024];
/*
OutOfMemoryError: Java heap space
内存溢出的错误,创建的数组太大了,超出了给JVM分配的内存
必须修改代码,创建的数组小一点
*/
}
}
2、异常的产生过程解析
package exception2;
/**
* created by apple on 2020/6/21
* 异常产生过程的解析,分析异常怎么产生,如何处理异常
*/
public class Demo02Exceptoin {
public static void main(String[] args) {
//创建int类型的数组,并赋值
int[] arr = {1,2,3};
int e = getElement(arr,3);
System.out.println(e); //ArrayIndexOutOfBoundsException
}
/*
定义一个方法,获取数组指定索引处的元素
*/
public static int getElement(int[] arr,int index){
int ele = arr[index];
return ele;
}
}

异常的处理
Java异常处理的五个关键字:try、catch、finally、throw、throws
3、抛出异常throw
throw小结
throw用在方法内,后面接一个异常对象,使用格式为throw new 异常类名(参数);,将这个异常对象传递到调用者处,并结束当前方法的执行。
throw使用的格式如下:
throw new NullPointerException("要访问的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
使用throw的实例使用:
package exception2;
/**
* created by apple on 2020/6/21
* throw
* 作用:
* 可以使用throw关键字在指定的方法中抛出指定的异常
* 使用格式:
* throw new xxxException("异常产生的原因");
* 注意事项:
* 1、throw 关键字必须写在方法的内部
* 2、throw 关键字 new的对象必须是Exception或Exception子类对象
* 3、throw 关键字 抛出指定的异常对象,我们必须处理这个异常对象
* a. throw关键字后边创建的是RuntimeException 或者RuntimeException的子类对象,我们可以不处理,默认交给JVM处理,打印异常对象,中断程序
* b. throw关键字后边创建的是编译异常(写代码的时候报错)就必须处理这个异常,要么throws,要么try catch
*/
public class Demo03Throw {
public static void main(String[] args) {
// int[] arr = null;
int[] arr = new int[3];
int e = getElement(arr,7);
}
/*
定义一个方法,获取数组指定索引处的元素
参数:
int[] arr
int index
以后在工作中,我们首先必须对方法中传递过来的参数进行合法性校验,如果参数不合法,我们必须用抛出异常的方式,告诉方法的调用者,传递的参数有问题。
注意:
NullPointerException是一个运行期异常,我们不用处理,默认交给JVM处理
ArrayIndexOutOfBoundsException是一个运行期异常,我们不用处理,默认交给JVM处理
*/
public static int getElement(int[] arr,int index){
/*
我们可以对传递过来的参数数组,进行合法性校验,如果数组arr的值是null,那么抛出空指针异常,告知方法的调用者,传递的数组的值是空
*/
if ( arr == null){
throw new NullPointerException("传递的数组的值是空");
}
/*
可以对index进行合法性校验。
如果index的范围不在数组索引范围内,
那我们就抛出数组索引越界异常,告知方法的调用者,"传递的索引超出数组索引使用范围"
*/
if (index < 0 || index > arr.length - 1){
throw new ArrayIndexOutOfBoundsException("数组索引越界");
}
int ele = arr[index];
return ele;
}
}
再来看看不使用throw的实例使用的运行:
public static void main(String[] args) {
//创建一个数组
int[] arr = {2,4,52,2};
//根据索引找对应的元素
int index = 4; //注意索引4已经越界了
int ele=arr[index];
System.out.println(ele);
System.out.println("over");
}
运行结果

这样一对比throw的优势就不言而喻了~
3.2、Objects非空判断_requireNonNul
package exception2;
import java.util.Objects;
/**
* created by apple on 2020/6/21
* Objects类中的静态方法 requireNonNull
* pubic static<T> T requireNonNull(T obj):查看指定引用对象不是null
*
*/
public class Demo04Objects {
public static void main(String[] args) {
method(null);
}
public static void method(Object obj){
//对传递过来的参数进行合法性判断,判断是否为null
/*if (obj == null){
throw new NullPointerException("传递的对象的值是null");
}*/
//简化代码
Objects.requireNonNull(obj);
Objects.requireNonNull(obj,"传递的对象的值是null");
}
}
声明异常throws
如果产生了问题,我们就会throw将问题描述类即异常进行抛出,也就是将问题返回给该方法的调用者。那么对于调用者来说,该怎么处理呢?一种是进行捕获处理,另一种就是继续讲问题声明出去,使用throws声明处理。
声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。
throws小结
关键字throws运用于方法声明之上,throws格式为修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ },用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
4、throws关键字_异常处理的第一种方法
package exception2;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* created by apple on 2020/6/21
* throws异常处理的第一种方式,交给别人处理
* 作用:
当方法内部抛出异常对象时,我们必须处理这个异常对象
可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理,自己不处理,别人处理,最终给JVM处理-->中断处理
* 使用格式:在方法声明时使用
修饰符 返回值类型 方法名(参数列表) throws AException, BException{
throw new AException("原因");
throw new BException("原因");
}
* 注意事项:
1、throws必须写在方法声明处
2、throws声明的异常必须是Exceptin或者Exception的子类
3、方法内部如果抛出多个异常对象,throws后面也必须声明多个异常, 如果抛出的多个异常对象,有父子类关系,那么直接声明父类异常即可
4、调用了一个声明抛出异常的方法,必须处理声明的异常, 要么继续使用throws声明抛出 ,交给方法的调用者处理,最终给JVM, 中断处理, 要么try catch 自己处理异常
*/
public class Demo05throws {
public static void main(String[] args) throws IOException {
read("c:\\a.txt");
}
/*
定义一个方法,对传递的文件路径进行合法性判断,如果路径不是"c:\\a.txt",抛出文件找不到异常对象,告知方法调用者
注意:FileNotFoundException是编译异常,抛出了编译异常,必须处理这个异常,可以使用throws继续声明抛出FileNotFoundException 对象,让方法的调用者处理
*/
public static void read(String filename) throws IOException {
if (!filename.equals("c:\\a.txt")){
throw new FileNotFoundException("传递的文件路径不对");
}
System.out.println("路径没有问题,读取文件");
if (!filename.endsWith("a.txt")){
throw new IOException("文件的后缀名不对");
}
}
}
throw 和 throws 的区别小结
throw:
1、表示方法内抛出某种异常对象
2、如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错
3、执行到 throw 语句则后面的语句块不再执行
throws:
1、方法的定义上使用 throws 表示这个方法可能抛出某种异常
2、需要由方法的调用者进行异常处理
5、try...catch_捕获异常,异常处理的第二种方式
如果异常出现的话,会立刻终止程序,所以我们得处理异常:
1、该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
2、在方法中使用try-catch的语句块来处理异常。
try-catch的方式就是捕获异常。
捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
package exception2;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* created by apple on 2020/6/21
* try catch 异常处理的第二种方式,自己处理异常
* try{
* 可能产生异常的代码
* }catch(定义一个异常的变量,用来接收try 中抛出的异常){
* 异常的处理逻辑,产生异常对象后,怎么处理对象。
* 一般在工作中,会把异常的信息记录在日志中。
* }
* ...
* catch(异常类名 变量名){
*
* }
* 注意:
1、try中有多个异常对象,可以使用多个catch处理这些异常对象
2、如果try中产生异常,会执行catch中的异常处理逻辑,执行完catch中的处理逻辑,继续执行try..catch之后的代码,
如果try中没有产生异常,不会执行catch中异常处理逻辑,执行完try中的代码,继续执行try。。catch之后的代码
*/
public class Demo06try {
public static void main(String[] args) {
try {
//可能产生异常的代码,
read("d://a.tt"); //输出:catch 传递的文件后缀不是。txt
// 后续代码
}catch (IOException e){ //try中抛出什么异常对象,catch就定义什么异常变量。用来接收异常对象
e.getStackTrace();
System.out.println("catch 传递的文件后缀不是.txt");
}
System.out.println("后续代码");
}
public static void read(String filename) throws IOException {
if (!filename.endsWith(".txt")){
throw new IOException("文件的后缀名不对");
}
System.out.println("文件名没有问题,读取文件");
}
}
输出:
catch 传递的文件后缀不是。txt
后续代码
6、Throwable类中3个异常处理的方法
1、String getMessage(), 返回此throwable的简短描述
2、String getString(), 返回此throwable的详细消息字符串
3、void printStackTrace(), Jvm打印异常对象,默认此方法,打印异常信息最全面
package exception2;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* created by apple on 2020/6/21
* try catch 异常处理的第二种方式,自己处理异常
* try{
* 可能产生异常的代码
* }catch(定义一个异常的变量,接收try 中抛出的异常){
* 异常的处理逻辑,产生异常对象后,怎么处理对象。
* 一般在工作中,会把异常的信息记录在日志中。
* }
* ...
* catch(异常类名 变量名){
*
* }
* 注意:
* 1、try中有多个异常对象,可以使用多个catch
* 2、如果try中产生异常,h会执行catch中的异常处理逻辑
* 执行完catch中的处理逻辑,继续执行try。。catch之后的带,啊
* 如果try中没有产生异常,不会执行catch中异常处理逻辑,执行完try中的代码
* 继续执行try。。catch之后的代码
*/
public class Demo06try {
public static void main(String[] args) {
try {
//可能产生异常的代码,
read("d://a.tt"); //输出:catch 传递的文件后缀不是。txt
// 后续代码
}catch (IOException e){ //try中抛出什么异常对象,catch就定义什么异常变量。用来接收异常对象
System.out.println(e.getMessage()); //简短信息 :文件的后缀名不对
System.out.println(e.toString()); //详细信息:重写Objects类的toString , java.io.IOException: 文件的后缀名不对
System.out.println(e); //默认调用toString方法 java.io.IOException: 文件的后缀名不对
e.printStackTrace(); //最全面
/*
java.io.IOException: 文件的后缀名不对
at exception2.Demo06try.read(Demo06try.java:45)
at exception2.Demo06try.main(Demo06try.java:30)
*/
e.getStackTrace();
System.out.println("catch 传递的文件后缀不是。txt");
}
System.out.println("后续代码");
}
public static void read(String filename) throws IOException {
if (!filename.endsWith(".txt")){
throw new IOException("文件的后缀名不对");
}
System.out.println("文件名没有问题,读取文件");
}
}
输出:
文件的后缀名不对
java.io.IOException: 文件的后缀名不对
java.io.IOException: 文件的后缀名不对
catch 传递的文件后缀不是。txt
后续代码
java.io.IOException: 文件的后缀名不对
at exception2.Demo06try.read(Demo06try.java:45)
at exception2.Demo06try.main(Demo06try.java:30)
7、finally代码块
有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
try 中有异常,就会给catch处理,导致,try后面的代码执行不到。
格式:
try{
可能产生异常的代码
}catch(定义一个异常的变量,用来接收try 中抛出的异常){
异常的处理逻辑,产生异常对象后,怎么处理对象。
一般在工作中,会把异常的信息记录在日志中。
}
...
catch(异常类名 变量名){
}finally{
无论是否出现异常都会执行
}
注意:
1、 finally不能单独使用,必须和try一起使用
2、finally 一般用于资源释放,无论是否出现异常,最后都要资源释放(IO)
8、异常的注意事项:多异常的捕获处理
1、多个异常分别处理
2、多个异常一次捕获,多次处理,
一个try 多个catch注意事项: catch里面定义的异常变量,如果有父子类关系,那么子类的异常变量必须写在上边,否则会报错,如下图所示:


3、多个异常一次捕获,一次处理,

总结:
1、运行时异常被抛出可以不处理,既不捕获也不声明抛出
2、如果finally有return语句,永远返回finally中的结果,避免该情况
3、如果父类抛出多个异常,子类重写父类方法时,抛出和父类相同的异常或者父类异常的子类或者不抛出异常
4、父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常,此时子类产生该异常,只能捕获处理,不能声明抛出
5、try catch 后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收
9、finally代码块与return语句
2、如果finally有return语句,永远返回finally中的结果,避免该情况
10、异常注意事项_子父类异常
f父类什么样,子类什么样
package exception2;
/**
* created by apple on 2020/6/21
* 字符类的异常
* 父类异常是什么样,子类也是什么样
*/
public class Fu {
public void show() throws NullPointerException,ClassNotFoundException{}
public void show02() throws IndexOutOfBoundsException{}
public void show03() throws IndexOutOfBoundsException{}
public void show04(){}
}
class Zi extends Fu{
//子类重写父类方法时 ,抛出和父类相同的异常
public void show() throws NullPointerException,ClassNotFoundException{}
//子类重写父类方法时,抛出父类异常的子类
public void show02() throws ArrayIndexOutOfBoundsException{}
//子类重写父类方法时,可以不抛出异常
public void show03(){}
//父类方法没有抛出异常,子类重写时,不能抛出异常
//public void show04(){}
//子类产生异常,只能捕获处理,不能声明抛出
public void show04() /*throws Exception */{
try {
throw new Exception("编译期异常");
} catch (Exception e) {
e.printStackTrace();
}
}
}
网友评论