一、案例引入
有时,我们写的代码会出现一些不正常的行为(除以0,使用空指针,数组越界),导致程序终止。
这其实不合理,举个例子:以前在打CF的时候,卡bug躲箱子里,游戏程序不会崩溃,而是会弹出一个错误代码的异常。
如下是除以0的异常:
public class Case01 {
public static void main(String[] args) {
int n1 = 10;
int n2 = 0;
int n3 = n1 / n2;
System.out.println("程序退出~");
}
}
最终程序并没执行输出语句,而是遇到除以0的时候终止了。
而使用异常处理,则可以提升代码的健壮性,让你的代码不再脆弱~
二、基本概念
在java中,程序执行中发生的不正常情况称为“异常”。语法错误和逻辑错误不算是异常!
2.1异常分类
1)Error :Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽、栈溢出.......
Error是严重错误,程序会崩溃。
2)Exception:其他因编程错误或偶然的外在因素导致的问题。如:空指针访问,试图读取不存在的文件,除以0......
Exception又分为两类:运行时异常——程序运行时,发生的异常,如:空指针访问
编译时异常——编程时,编译器检查出的异常。如:试图读取不存在文件。
编译时异常是编译器要求必须处置的异常!
常见异常的体系图(精简版):
图中蓝色为运行异常,红色为编译异常。
至此,可以得出运行异常一般是程序员的逻辑错误,是程序员应该避免的出现的,编译时异常,编译器会帮你检查出来,所以一定要显示的处理,才能编译。
三、异常的处理
光知道啥是异常可不行,还得会处理。
异常处理分为2种方式:1)利用try-catch-finally, 在代码中捕获异常,自行处理。
2)利用throws,将发生的异常抛出,交给调用者来处理。
如果程序员没有显示的处理异常,则默认是throws
3.1try-catch-finally
基本介绍:
注意:如果try中的某一行出现了异常,则后面的语句不再执行,直接进入catch语句中。
使用:
public class Exception_ {
public static void main(String[] args) {
try{
int n = 10 / 0; //故意除以0
System.out.println("try中在出现异常的代码之后的代码~");
} catch (Exception e){
System.out.println(e.getMessage());
} finally{
System.out.println("finally中的语句执行~");
}
}
}
输出:
总结:1)如果try中代码出现异常,则在这句代码后的代码不会执行,而是直接执行catch中的,如果没有异常,会执行完try中所有代码,并且不会执行catch中的代码。
2)如果有finally,不管有没有异常,最终都会执行,因此可以将重要的代码放在fianlly中(关闭连接,释放资源等)。
3.2throws
基本介绍:
如果一个方法中语句可能出现异常,但我又不想处理,可以使用throws,将异常抛出,交给调用者处理,如果调用者还不处理,就交给调用者的调用者,直到JVM来给你处理(我什么身份啊~)。
注意: throws是写在方法后面的,throws后面声明的抛出异常(可以写多个)可以是方法中产生的异常类型,也可以是它的父类,当子类继承了这个方法,所抛出的异常类型要么跟父类一样,要么为其子类。
重写的方法所抛出的异常,必须为父类所抛出的,或为其子类~
四、自定义异常
4.1案例引入:
当我们想让用户输入一个数据在我们想要的范围,可用户很叛逆,偏偏就不。
public class Throw_ {
public static void main(String[] args) {
System.out.println("请输入1-10");
Scanner scanner = new Scanner(System.in);
int input = scanner.nextInt();
if(!(input >= 1 && input <= 10)){
System.out.println("输入数据不再指定范围~");
}
}
}
我们只能低声下气的说一声输入错误。
而如果使用自定义异常,我们就能站着说话了!
public class Throw_ {
public static void main(String[] args) {
test();
}
public static void test(){
System.out.println("请输入1-10");
Scanner scanner = new Scanner(System.in);
int input = scanner.nextInt();
if(!(input >= 1 && input <= 10)){
throw new DataBoundException("输入不在指定范围内");
}
}
}
class DataBoundException extends RuntimeException{
private String message;
public DataBoundException(String message) {
super(message);
this.message = message;
}
public void Tell(){
System.out.println("你小子输入有误!" + message);
}
}
输出:
由于没有让程序员处理异常,而是让JVM来处理,所以直接中断了程序。
当然,我们也可以用try-catch来处理
public static void main(String[] args) {
try {
test();
} catch (DataBoundException e) {
e.Tell();
}
}
输出:
这样写,可以更灵活~
4.2基本介绍
自定义异常可以继承Exception或者RuntimeException
如果继承Exception,属于编译异常, 如果继承RuntimeException,属于运行异常。
4.3throw VS throws
throws : 是一种异常处理方式,写在方法的声明处,后面跟着的是 异常类型。
throw : 是手动生成异常对象的关键字,写在方法体中,后面跟着的是 异常对象。