1. 异常的体系结构和异常的分类
异常就是程序出现了不正常的情况,导致JVM非正常终止,代码语法错误不在异常体系之中。
异常的体系结构:
- 编译时异常:在编译成class文件时必须要处理的异常,也称为受检异常
- 运行时异常:在编译过程中不需要处理,在运行字节码文件时可能会出现的异常
2. JVM默认处理异常的方式
当代码出现了异常,那么就会在异常处创建一个异常对象,若程序没有自己处理异常的代码,就会将异常交给本方法的调用者处理。
JVM默认处理异常的方式:
- 将异常信息以红色字体展示在控制台上(异常原因、名字 、位置)
- 停止程序运行,哪里出现异常就在哪里停止
3. 异常处理方式
3.1 throws声明异常
格式:public void 方法() throws 异常类名
注意事项:
- 书写位置在方法的括号后面,表示声明一个异常
- 编译时异常必须要进行处理,throws声明异常表示,谁调用这个方法谁处理异常
- 运行时异常因为在运行时才会发生,所以在方法后面可以不写,默认交给jvm处理
示例代码:
public class Demo02 {
public static void main(String[] args) throws ParseException {
method1();//如果调用者没有处理异常的代码,最终交给Main方法调用者JVM处理异常
}
//throws声明,告诉调用者调用这个方法可能会发生异常
//若无异常,方法正常执行;若发生异常将异常交给调用者处理
private static void method1() throws ParseException {
String s = "2021年11月11日";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date d = sdf.parse(s);//有可能会产生异常
System.out.println(d);
}
}
3.2 throw抛出异常
- 格式:throw new 异常();
- 注意:这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
throws和throw的区别:
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常 | 表示手动抛出异常对象,由方法体内的语句处理 |
抛出异常的意义:
- 在方法中,当传递的参数有误,没有继续运行下去的意义了,则采取抛出处理,表示让该方法结束运行
- 告诉调用者方法中出现了问题
public class ExceptionDemo {
public static void main(String[] args) {
int [] arr = null;
printArr(arr);//就会 接收到一个异常.
//我们还需要自己处理一下异常.
}
private static void printArr(int[] arr) {
if(arr == null){
//调用者知道成功打印了吗?
//System.out.println("参数不能为null");
throw new NullPointerException();
//当参数为null的时候,手动创建了一个异常对象,抛给了调用者
//调用者就知道没有打印成功
}else{
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
3.3 try-catch自己处理异常
此方法处理异常的好处:即使发生了异常,程序还可以继续执行
示例代码:
public class Demo01 {
public static void main(String[] args) {
int[] arr = null;
try {
//有可能会出现异常的代码
printArr(arr);
}catch (NullPointerException e){
//若出现了这样的异常,我们进行的操作
System.out.println("数组为空");
}
//程序不会终止,会继续执行
System.out.println("嘿嘿嘿");
}
private static void printArr(int[] arr) {
if (arr == null){
//抛出异常
throw new NullPointerException();
}else {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
}
注意事项:
- 如果 try 中没有遇到异常,会把try中所有的代码全部执行完毕,不会执行catch里面的代码
- 如果 try 中遇到了异常,那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
- 如果出现的异常没有被捕获,那么try...catch就相当于没有写,异常默认交给虚拟机处理
- 若出现多个异常就写多个catch,如果多个异常之间存在子父类关系,那么父类要写在子类异常的下面
4. Throwable类常用方法和自定义异常类
Throwable常见方法:
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
自定义异常类:
- 当Java中提供的异常不能满足我们的需求时,我们可以自定义异常,让异常信息更加的见名知意
- 实现步骤: 1. 定义异常类;2. 写继承关系;3. 提供空参构造;4. 提供带参构造
练习
案例需求:
- 键盘录入学生的姓名和年龄,其中年龄为18 - 25岁;
- 超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止
自定义异常AgeOutOfBoundsException
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
创建学生对象代码:在setAge方法中判断年龄抛出自定义异常AgeOutOfBoundsException
package com.yulu.yichang;
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age >= 18 && age <= 25){
this.age = age;
}else {
//如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常
throw new AgeOutOfBoundsException("年龄超出范围!");
}
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
键盘录入姓名和年龄,并赋值给学生对象,如果是非法数据就再次录入
package com.yulu.yichang;
import java.util.Scanner;
public class ExceptionDemo {
public static void main(String[] args) {
Student student = new Student();
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
student.setName(name);
while(true){
System.out.println("请输入学生年龄:");
String strage = sc.nextLine();
try {
int age = Integer.parseInt(strage);
student.setAge(age);
//无异常则退出循环
break;
} catch (NumberFormatException e) {
//针对int age = Integer.parseInt(ageStr);捕获异常
System.out.println("请输入一个整数");
continue;
} catch (AgeOutOfBoundsException e){
//针对Student类中年龄限制抛出异常
System.out.println(e.toString());
System.out.println("请输入一个18-25岁的年龄");
continue;
}
}
//打印学生对象字符串(toString)
System.out.println(student);
}
}
如有错误欢迎留言评论,及时更正。 2021年5月28日 羽露风