07-异常、分类、throws、throw、try-catch、Throwable、自定义异常
原创
©著作权归作者所有:来自51CTO博客作者武大保安的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
1.异常
1.1 异常(记忆)
- 异常的概述
异常就是程序出现了不正常的情况(程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止)
注意:语法错误不在异常体系中 - 异常的体系结构
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_自定义异常](https://s2.51cto.com/images/blog/202209/19153553_63281bd9aaf8383804.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1、整个java异常体系的根类,Throwable
2、Error 比如内存溢出,只有加内存条才行,代码是无法解决的
3、Exception:需要学习的异常
4、Exception分为RuntimeException,和非RuntimeException
5、RuntimeException:运行时异常,写代码时可以不捕获,然后一旦出现就终止该线程
6、非RuntimeException:编译时异常,写代码时必须捕获(或者throws),否则编译不了(捕获处理后(try…carch)就算触发了,程序还可以继续往下执行)
1.2 编译时异常和运行时异常的区别(记忆)
- 编译时异常 (非RuntimeException)
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译 (写代码时必须处理,try…catch或者throws,否则编译不过)
- 都是RuntimeException类及其子类
- 无需显示处理,也可以和编译时异常一样处理 (编译时可以处理,也可以不处理,编译都通过)
- 图示
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcSJGBLu-1653452709475)(img\02_编译时异常和运行时异常.png)] 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_异常_02](https://s2.51cto.com/images/blog/202209/19153553_63281bd9d2ce747507.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1.3 JVM默认处理异常的方式(理解)
- 如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
- 把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
- 程序停止执行(也就是说一旦被触发的异常不是程序员自己处理的,被jvm感知到了,jvm处理后一定会终止程序的执行)
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_自定义异常_03](https://s2.51cto.com/images/blog/202209/19153554_63281bda0751559903.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1.4 查看异常信息 (理解)
控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置
我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6XJew5xg-1653452709476)(img\03_查看异常信息.png)] 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_异常_04](https://s2.51cto.com/images/blog/202209/19153554_63281bda39c5544656.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
介绍自己处理异常的三种方式
1.5 throws方式处理异常(应用)
public void 方法() throws 异常类名 {
}
public class ExceptionDemo06 {
public static void main(String[] args) {
method1();
}
private static void method1() {
int[] arr = null;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_运行时异常_05](https://s2.51cto.com/images/blog/202209/19153554_63281bda6c06a67558.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
public class ExceptionDemo06 {
public static void main(String[] args) {
method1();//此时调用者也没有处理,还是会交给JVM暴力解决
}
//throws方案说明:
//1.告诉调用者,你调用我,有可能会出现这样的异常哦
//2.如果方法中没有出现异常,那么正常执行
//3.如果方法中真的出现了异常,那么将这个异常交给调用者处理
private static void method1() throws NullPointerException{
int[] arr = null;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
抛出了,但是调用者也没有处理,因此执行结果同上
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_java_06](https://s2.51cto.com/images/blog/202209/19153554_63281bdabca2b5271.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
同样,编译时异常(非RuntimeException)也同上。(方法里可以throws,此时调用者不想处理也必须throws,否则编译不过)
当然了:
运行时异常,方法声明时可以不写throws
编译时异常,方法声明时(不捕获的话)必须throws,否则直接报错,编译不过
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_自定义异常_07](https://s2.51cto.com/images/blog/202209/19153554_63281bdadda5865179.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
查看源码:该异常继承自RuntimeException就是运行时异常
该异常继承自Exception就是编译时异常
1.6 throw抛出异常 (应用)
- 格式
throw new 异常(); - 注意
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了 - throws和throw的区别
throws
| throw
|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常
| 表示手动抛出异常对象,由方法体内的语句处理
|
- 抛出处理异常的意义 (throw new 异常类())
1、在方法中,当传递的参数有误,没有继续运行下去的意义了,则采取抛出处理,表示让该方法结束运行。
2、告诉调用者方法中出现了问题 - 示例代码1 (引入)
public static void main(String[] args) {
System.out.println("床前明月光");
System.out.println("疑是地上霜");
System.out.println("举头望明月");
String lastStr="低头喝鸡汤";
if(lastStr.contains("鸡汤")){
throw new RuntimeException();
//当代码执行到这里,就创建了一个异常
//该异常创建之后暂时没有手动处理,抛给了调用者处理
//下面的代码不会再执行了
}
System.out.println(lastStr);
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_java_08](https://s2.51cto.com/images/blog/202209/19153555_63281bdb110fe26682.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
printArr(arr);
arr = null;
printArr(arr);//方法里throw了 此处就会触发异常的
System.out.println("我最帅");//前面异常一旦被捕获处理 此处是可以正常执行的 !!!!★★
}
private static void printArr(int[] arr) {
if (arr != null) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
} else {
//System.out.println("arr不能为null");//只有这一行不行 只是在控制台简单提示了下(形式和没错误一样)
//必须 明显地 反馈给调用者 此方法执行出错了 【所以开发中下面这行代码的形式是不能少的】
throw new NullPointerException();//调用者会收到这个异常 【会提示 "printArr(arr);行" 有错误】
}
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_自定义异常_09](https://s2.51cto.com/images/blog/202209/19153555_63281bdb32b8e11701.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1.7 try-catch方式处理异常(应用)
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
自己的异常的处理代码;
}
- 程序从 try 里面的代码开始执行
- 出现异常,就会跳转到对应的 catch 里面去执行
- 好处: 执行完毕之后,程序还可以继续往下执行
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
printArr(arr);
arr=null;
try {
printArr(arr);//方法里为何要throw? 答案在这里 交给调用者来处理(先捕获 然后爱咋处理咋处理)
} catch (NullPointerException e) {
System.out.println("arr不能为null");//自己捕获处理了 就不会终止程序 会继续往下执行的★
}
System.out.println("我最帅");//前面异常一旦被捕获处理 此处是可以正常执行的 !!!!★★
}
private static void printArr(int[] arr) {
if(arr!=null){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}else{
//System.out.println("arr不能为null");//只有这一行不行 只是在控制台简单提示了下(形式和没错误一样)
//必须 明显地 反馈给调用者 此方法执行出错了 【所以开发中下面这行代码的形式是不能少的】
throw new NullPointerException();//调用者会收到这个异常 【会提示 "printArr(arr);行" 有错误】
}
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_java_10](https://s2.51cto.com/images/blog/202209/19160306_6328223a4bd587160.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=,x-oss-process=image/resize,m_fixed,w_1184)
- 如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码 - 如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码 - 如果出现的问题没有被捕获,那么程序如何运行?
那么try…catch就相当于没有写.那么也就是自己没有处理.
默认交给虚拟机处理.(终止程序) - 同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.
注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
- 如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_11](https://s2.51cto.com/images/blog/202209/19153600_63281be060bc149273.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
2. 如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
代码同上:
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_12](https://s2.51cto.com/images/blog/202209/19153600_63281be08d18b7032.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
- 如果出现的问题没有被捕获,那么程序如何运行?
那么try…catch就相当于没有写.那么也就是自己没有处理.
默认交给虚拟机处理.(终止程序) ![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_13](https://s2.51cto.com/images/blog/202209/19153600_63281be0b219597841.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_14](https://s2.51cto.com/images/blog/202209/19153600_63281be0cf8b487066.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
- 同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.
注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面 ![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_15](https://s2.51cto.com/images/blog/202209/19153600_63281be0f1f8616172.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_16](https://s2.51cto.com/images/blog/202209/19153601_63281be12b32586225.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1.8 Throwable成员方法(应用)
Throwable是所有异常类的父类,所以所有异常类对象都可以调用下面3个方法
方法名
| 说明
|
public String getMessage()
| 返回此 throwable 的详细消息字符串
|
public String toString()
| 返回此可抛出的简短描述
|
public void printStackTrace()
| 把异常的错误信息输出在控制台
|
public static void main(String[] args) {
try {
int[] arr={1,2,3,4,5};
System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
System.out.println(e.toString());
System.out.println("执行了吗?");
e.printStackTrace();
}
System.out.println("我若输出了,就证明红字不是虚拟机自带输出的~");
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_示例代码_17](https://s2.51cto.com/images/blog/202209/19153601_63281be14e45249144.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
java8 提示少 顺序还不对
1.9 异常的练习 (应用)
- 需求
键盘录入学生的姓名和年龄,其中年龄为18 - 25岁,超出这个范围是异常数据不能赋值.需要重新录入,一直录到正确为止 - 实现步骤
- 创建学生对象
- 键盘录入姓名和年龄,并赋值给学生对象
- 如果是非法数据就再次录入(写在set方法里 调用时捕获异常 最为便捷、科学、不遗忘)
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
if(age<=25&&age>=16){
this.age = age;
}else {
throw new RuntimeException("年龄超出了范围");
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Student s = new Student();
System.out.println("请输入姓名:");
String name = sc.nextLine();
s.setName(name);
while (true){
System.out.println("请输入年龄:");
String ageStr = sc.nextLine();
try {
int age = Integer.parseInt(ageStr);
//if(age>=16&&age<=25){}//每次录入前都这么判断麻烦且容易忘 用异常最好
s.setAge(age);
break;//此处跳出 一旦setAge成功就跳出嘛
} catch (NumberFormatException e) {//范围小的异常放在前面
System.out.println("请输入一个整数");
continue;
}catch (RuntimeException e){
System.out.println("请输入一个符合范围的年龄");
continue;
}
}
System.out.println(s);
}
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_java_18](https://s2.51cto.com/images/blog/202209/19153601_63281be17c28d47255.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
1.10 自定义异常(应用)
- 自定义异常概述
当Java中提供的异常不能满足我们的需求时,我们可以自定义异常 - 实现步骤
- 定义异常类
- 写继承关系
- 提供空参构造
- 提供带参构造
继承好RuntimeException (或者Exception编译时异常)
加上一个空参、一个带参构造方法即可(查看源代码模仿着写得)(构造方法可以自动生成)
自定义异常类编写完毕(更加见名知意而已)
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
Student.java 修改一处
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_自定义异常_19](https://s2.51cto.com/images/blog/202209/19153601_63281be1a8fd696098.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
ExceptionLxStudent.java修改一处
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_运行时异常_20](https://s2.51cto.com/images/blog/202209/19153601_63281be1ca32472920.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
![在这里插入图片描述 07-异常、分类、throws、throw、try-catch、Throwable、自定义异常_java_21](https://s2.51cto.com/images/blog/202209/19153602_63281be21f38742344.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
Optional 类 有机会补到上一篇博客
小知识:
查看源码:该异常继承自RuntimeException就是运行时异常
该异常继承自Exception就是编译时异常