Throwable类是Java语言中所有异常和错误的超类(可以理解为是仅次于之前学的Object顶级类的超类)。只有作为此类(或其一个子类)的实例的对象有Java虚拟机抛出,或者可以由Java throw语句抛出
Throwable的两个子类的实例'Error'和'异常'通常用于表示出现异常情况
Error:表示严重的问题,合理的应用程序不应该试图捕获(即此时java程序是无能为力的),大多数这样的错误是异常情况。例如硬件层面的问题、内存资源不足等
异常:表示合理应用程序可能想要捕获的条件,这里的条件指的是异常 检查异常:'异常类'和'不是RuntimeException的子类的任何类',检查异常是编译期间必须要处理的,否则程序不会被编译更不会运行
RuntimeException类的异常:是在Java虚拟机的正常操作期间可以抛出的异常的超类。例如索引越界 RuntimeException及其子类的异常:是未经检查的异常,即在编译期间是不需要检查的,出现问题才需要自行检查代码
总结: 1、异常就是程序出现了不正常的情况 2、异常体系指Throwable。Throwable又分为Error、Exception。Exception又分为RuntimeException、非RuntimeException 3、Error是严重问题,不需要处理 4、Exception是异常类,表示程序本身可以处理的问题 5、Exception中的RuntimeException表示在编译期间是不检查的,出现问题后,需要我们回来修改代码 6、Exception中的非RuntimeException表示在编译期间必须处理,否则程序不能被编译,更不能运行
异常的练习
xxxxxxxxxxpackage ch13;
public class a_1_1测试 {
public static void main(String[] args) { methods(); }
public static void methods(){ int[] arr = {1,2,3};//定义数组 System.out.println(arr[1]);//通过索引1访问数组中的元素
//对于数组会有索引越界异常,如下 System.out.println(arr[99]); //报错ArrayIndexOutOfBoundsException }
}
JVM的默认处理异常方案
默认处理具体做了如下的事情: 1、把异常的名称,异常的原因即异常出现的位置等信息输出在了控制台 2、程序停止执行
JVM默认处理异常方案的练习
x
package ch13;
public class a_2_1测试 {
public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); }
public static void method(){ int[] arr = {1,2,3}; System.out.println(arr[99]); }
/*上面代码的输出如下: 开始 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 99 out of bounds for length 3 at ch13.a_2_1测试.method(a_2_1测试.java:13) at ch13.a_2_1测试.main(a_2_1测试.java:7)*/
//其中JVM的异常处理如下 //ArrayIndexOutOfBoundsException:异常的名称 //Index 99 out of bounds for length 3:异常的原因 //at ch13.a_2_1测试.method(a_2_1测试.java:13):异常的位置
}
异常处理_trycatch
JVM的默认处理会把程序停止运行,是非常不便于实际开发的。于是,我们来学一下怎么自己处理异常,如下
异常处理 如果程序出现了问题,我们需要自己来处理,有两种方案: 1、使用try...catch... (对于编译时异常,经常使用这种处理方案) 2、使用throws
这里先学习'使用try...catch...'的处理方案,格式如下
xxxxxxxxxxtry{ 可能出现异常的代码;} catch(异常类名 变量名){ 异常的处理代码;}'使用try...catch...'处理方案的执行流程,如下 1、程序从try里面的代码开始执行 2、出现异常,会自动生成一个异常类对象,该异常类对象奖杯提交给java运行时系统 3、当java运行时系统接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理 4、执行完毕后,程序还可以继续往下执行
异常处理_trycatch的练习
x
package ch13;
//这节课的测试,要结合上一节课,即'a_2_1测试'一起来看public class a_3_1测试 {
public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); }
public static void method(){ try{ int[] arr = {1,2,3}; System.out.println(arr[99]);//这行出现问题后会产生一个异常类对象。相当于这行new了一个异常,即new ArrayIndexOutOfBoundsException //上面那行会把异常类对象提交给java的运行时系统。然后运行时系统就会在catch里面找匹配,如果匹配就执行catch里面的代码 } catch(ArrayIndexOutOfBoundsException e){//这个e是对象,即可以调用方法 //System.out.println("你访问的数组的索引不存在"); //这样输出错误提示会比较单调,因为具体的错误并没有在控制台输出 e.printStackTrace(); //这样就即保证了程序继续往下执行,又可以输出具体的异常信息。printStackTrace方法在下一节课有说,即'a_4_0Throwable的成员方法' } }
//这节课和上节课的共同点是代码都出现了同样的问题 //这节课和上节课的不同点如下: //1、上节课的错误由JVM默认处理,不会继续往下执行程序 //2、这节课的错误由我们自己处理,程序可继续往下执行,并且在报错的地方可以自行添加输出信息
}
Throwable的成员方法
Throwable是所有错误和异常的祖宗类(超类),即Throwable的所有子类都可以使用Throwable的成员方法。Throwable的成员方法如下
| 方法名 | 说明 |
|---|---|
| public String getMessage() | 返回此Throwable的详细信息字符串 |
| public String toString() | 返回此可抛出的简短描述 |
| public void printStackTrace() | 把异常的错误信息输出在控制台 |
Throwable成员方法的练习
x
package ch13;
//可结合上一节课的'a_3_1测试'一起理解public class a_4_1测试 {
public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); }
public static void method(){ try{ int[] arr = {1,2,3}; System.out.println(arr[99]); } catch(ArrayIndexOutOfBoundsException e){
//public void printStackTrace() 把异常的错误信息输出在控制台 //e.printStackTrace(); //该方法是3个方法中输出的异常信息最多的
//public String getMessage() 返回此Throwable的详细信息字符串 //System.out.println(e.getMessage());;//想了解getMessage方法的底层是怎么实现的,可选中getMessage,再按Ctrl+B
//public String toString() 返回此可抛出的简短描述 System.out.println(e.toString());//输出异常原因以及类名,这个方法的输出包含了getMessag输出的内容 } }}
编译时异常和运行时异常的区别
java中的异常被分为两大类:'编译时异常'和'运行时异常',也被称为'受检异常'和'非受检异常'
所有的RuntimeException类及其子类被称为'运行时异常',其他的异常都是'编译时异常'
什么是编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
什么是运行时异常:无需显示处理,也可以和'编译时异常'一样处理
编译时异常和运行时异常区别的练习
x
package ch13;
import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;
public class a_5_1测试 {
public static void main(String[] args) { //method();//要调用才会执行。可以发现控制台报错了,这种是运行时异常,我们需要回到自己的代码里进行修改 method2(); }
//------------------------------------------------------------------------------------------------------------
//运行时异常,先注释有需要自行解开 /*public static void method() { int[] arr = {1, 2, 3}; System.out.println(arr[99]); }*/ //解决'运行时异常'的方案,如下。对于运行时异常,写方案只是告诉我们哪里出错了,但真正的解决还是我们需要回到自己的代码里进行修改 /*public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[99]); } catch (ArrayIndexOutOfBoundsException e){ e.printStackTrace(); } }*/ //先注释,需要自行解开
//--------------------------------------------------------------------------------------------------------------
//编译时异常,先注释有需要自行解开 /*public static void method2(){ //可以回去看前面学的Date类,之前我们在学习Date类时经常会对parse进行异常处理 String s = "2022-5-20"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); //典型的编译时异常,我们需要通过try…catch来处理 System.out.println(d); }*/ //解决'运行时异常'的方案,如下。对于编译时异常,写方案就能解决报错 public static void method2(){ //可以回去看前面学的Date类,之前我们在学习Date类时经常会对parse进行异常处理 try{ String s = "2022-5-20"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); System.out.println(d); } catch(ParseException e){ //注意ParseException是对应的异常类名称 e.printStackTrace(); }
}}
异常处理_throws
虽然我们通过try…catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理,也就是说,有些时候可能出现的异常是我们处理不了的,这个时候就需要使用throws这个异常处理方案
throws异常处理方案的格式:
throws 异常类名;总结: 1、编译时异常必须要进行处理,两种处理方案:try…catch…和throws,如果使用的是throws这种方案,将来谁调用谁处理 2、运行时异常可以不处理,出现问题后,需要我们回来修改代码
异常处理_throws的练习
xxxxxxxxxxpackage ch13;
import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;
public class a_6_1测试 {
public static void main(String[] args) { System.out.println("开始"); //method(); //这里对应的是36行那里的被注释的代码块
try { //这个try方案才是真正能解决异常的,try的代码是由于14行的快捷键才出现的(也可自己手写) method2(); //当28行抛出异常后,这里的method2就会报红线。同样也是选中method2,按Alt+enter,点击Surround…… } catch (ParseException e) { e.printStackTrace(); } System.out.println("结束"); }
//----------------------------------------------------------------------------------------------------
//编译时异常。注意throws ParseException是28行那里按了Alt+enter,点击Add才出现的(也可自己手写)。这个实际就是异常处理的throws方案 public static void method2() throws ParseException { String s = "2022-5-20"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); //需要选中parse,按Alt+enter,点击Add……。在之前将过这个快捷键,现在就正式了解是干嘛的 System.out.println(d); } //注意,这个错误只是抛出,不过在13行那里进行了真正的解决
//-----------------------------------------------------------------------------------------------------
//运行时异常。使用throws时,直接把throws ArrayIndexOutOfBoundsException加到下面那一行。这个实际就是异常处理的throws方案 /*public static void method() throws ArrayIndexOutOfBoundsException{ int[] arr = {1,2,3}; System.out.println(arr[99]); } //注意,这个错误只是抛出,并没有真正处理。对应的是11行的代码*/ //这部分代码块只是抛出,没有处理,所以注释了,要处理的话在11行使用try就能处理
//------------------------------------------------------------------------------------------------------ //总结:throws只是把异常抛出去(其实就是延迟处理,不是一种具体的处理),并且还会让程序停止运行,并没有解决异常 //如果需要真正处理,就需要使用try…catch。被try处理后,程序不会停止,还会继续运行
}
自定义异常
自定义异常的格式
x
public class 异常类名 extends Exception{ 无参构造 带参构造}throws和throw的区别,如下
xthrows: throw1、用在方法声明后面,跟的是异常类名 1、用在方法体内,跟的是异常对象名2、表示抛出异常,由该方法的调用者来处理 2、表示抛出异常,由方法体内的语句处理3、表示出现异常的一种可能性,并不一定会发生这些异常 3、执行throw一定抛出了某种异常,即被throw抛出,那一定是异常例如我们这个打分案例,只要score在0~100就不会发生异常超出范围就会异常被抛出
自定义异常的练习
x
package ch13;
//注意自定义异常类必须要继承Exception或RuntimeException。Exception是编译时异常,RuntimeException是运行时异常public class a_7_1自定义异常类 extends Exception {
//无参构造方法。控制台会显示异常名称和异常发生的位置,但异常的原因不会显示 public a_7_1自定义异常类(){}
//带参构造方法 public a_7_1自定义异常类(String message){ super(message); //想深入了解可选中super,按Ctrl+B跟进源码,进去另一个页面后再选中super……。可以知道message是传到Throwable里面了 } }xxxxxxxxxxpackage ch13;
public class a_7_2Teach {
//需要在下一行用throws把异常类抛出来 public void checkScore(int score) throws a_7_1自定义异常类{ if(score<0 || score>100){ //当小于0或者大于100时,就不适合我们评分,即出现问题了,我们需要把符合if逻辑的错误判断抛出,如下 //throw new a_7_1自定义异常类(); //throw跟的是对象。用于在方法体中抛出错误对象 //上面那行是抛给无参构造方法。控制台会显示异常名称和异常发生的位置,但异常的原因不会显示。所以报错不太具体,我们使用带参,如下 throw new a_7_1自定义异常类("error 请输入0~100的数字"); //带参,可以把报错的原因反馈给用户。注意这里是throw } else{ System.out.println("分数正常"); } }}x
package ch13;
import java.util.Scanner;
public class a_7_3测试 {
public static void main(String[] args){
while (true) { //这个只是循环,不加循环也行 //键盘录入分数 Scanner sc = new Scanner(System.in); System.out.println("请输入分数"); int score = sc.nextInt();
//创建Teach类对象 a_7_2Teach t = new a_7_2Teach(); try { //这个try不是我们自己写的,是由于17行的快捷键生成的。当然自己写也可以 //由于我们自定义的异常是编译时异常,所以这行的checkScore会报红线,解决:选中checkScore,按Alt+enter,点击Surr… t.checkScore(score); } catch (a_7_1自定义异常类 e) { e.printStackTrace(); }
System.out.println("-------------------");
//该案例如果我们输入的是[0,100]就不会报错,但是如果输入的是其他就会报错,是因为我们在这个案例继承了我们定义的异常类 } }}