首先上图
如图,Throwable是父类,用来定义所有可以被称为异常抛出的类。
Throwable包括Error和Exception两大类。
Error定义:不希望被程序捕获或者是程序无法处理的错误。
Exception定义:用户程序可能捕捉的异常情况或者说是程序可以处理的异常。
两者从定义可以看出来显然不一样。
这次主要说一说Exception。
Exception包括运行时异常(RuntimeException)和非运行时异常,也称编译时异常。
Java常见的异常类型:
一般而言,运行时异常指空指针异常、数组下标越界异常、算数异常、类型转换异常等。
空指针异常举例:
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
ListNode listNode = null;
System.out.println(listNode.next);
}
上述代码运行时会报如下错:
Exception in thread "main" java.lang.NullPointerException
at java_test.Test_3.main(Test_3.java:19)
第19行就是“System.out.println(listNode.next);”这一行代码。由于没有创建ListNode新对象,所以虽然编译的时候不报错,运行时却会显示NullPointerException
数组下标越界异常举例:
int[] array = new int[10];
System.out.println(array[10]);
上述代码运行时会报如下错:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
at java_test.Test_3.main(Test_3.java:21)
由于数组定义时只有10,即下标为0~9,所以在输出array[10]会显示ArrayIndexOutOfBoundsException
算数异常举例:
System.out.println(10 / 0);
上述代码运行时会报如下错:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at java_test.Test_3.main(Test_3.java:21)
第21行就是如上代码。我们都知道分母不为0,虽然在编译时10/0不会显示错误,但是运行时显然报错了。
类型转换异常举例:
在Student类里面设一个有Object参数的构造函数,用强制类型转换赋值
public Student(Object obj) {
Student student =(Student)obj;
}
调用
public static void main(String[] args) {
Teacher teacher = new Teacher();
Student student = new Student(teacher);
}
上述代码运行时会报如下错:
Exception in thread "main" java.lang.ClassCastException: java_test.Teacher cannot be cast to java_test.Student
调用student的构造函数时,虽然teacher对象可以自动转换为Object对象,但是转换成Student对象时会发现两者无法转换,所以报错ClassCastException。
异常处理:
1.抛出异常。
通过throws在函数签名(包括参数及参数类型,返回值及类型,可能抛出或传回的异常,关键字等)抛出异常,等待下一个使用者处理。
2.try-catch 方法(有可能有finally)
格式:
try{
需要检查的代码(有可能是正常代码,也有可能是异常代码)
} catch(异常的类型1 异常类型的变量1){
捕获异常后要处理异常
} catch(异常的类型2 异常类型的变量2){
捕获异常后要处理异常
} finally{
一定会执行的代码(不论是否抛出异常)
}
在try中放入可能出错的代码块,一旦运行到某处,出现异常,捕捉异常,到对应的catch块内执行代码。finally一定会执行。
3.自定义异常
与2相比多出一个需要自己写自定义异常类,一旦捕捉到异常,用自定义异常类进行处理
格式:
class MyException extends Exception {
MyException(String ErrorMessage){
supper(ErrorMessage);
}
}
try{
需要检查的代码(有可能是正常代码,也有可能是异常代码)
} catch(MyException(自定义异常类的类型) 异常类型的变量){
捕获异常后用自定义异常类来处理异常
}
举例:
public class MeiQianException extends Exception{
private Double money;
public MeiQianException(Double money) {
super("余额不足还差:" + money);
this.money = money;
}
}
public class AccountAdmin {
// 余额
private Double balance;
public AccountAdmin(Double balance) {
this.balance = balance;
}
// 存钱
public void deposit(double money) {
balance+= money;
}
// 取钱
public void withdraw(double money) throws MeiQianException {
if (balance >= money) {
balance -= money;
} else {
double needMoney = money - balance;
// 当取钱余额不足的时候,给调用者抛出一个异常,而且这个异常
// 是编译时异常,需要取钱调用这个方法的人必须要未雨绸缪处理
throw new MeiQianException(needMoney);
}
}
public static void main(String[] args) {
AccountAdmin accountAdmin = new AccountAdmin(30000.0);
accountAdmin.deposit(3000);
try {
accountAdmin.withdraw(4000);
} catch (MeiQianException e) {
e.printStackTrace();
} finally {
System.out.println("finally");
}
System.out.println("AccountAdmin.main");
}
}