目录
异常体系结构
异常(Exception)是一个个类,错误和异常都继承于Throwable
错误:指java虚拟机无法解决的问题,比如JVM内部错误,资源耗尽,栈溢出,堆溢出就是错误
异常可以被抛出,但是错误不能被抛出
只是罗列部分异常和大致结构
异常又分为两大类:
编译时异常(受查异常):编译的时候系统爆出的异常
例如:
运行时异常(非受查异常):RuntimeException
处理异常
异常主要关键字:throw,throws,try,catch,final
异常的抛出
异常不仅可以通过系统抛出,也能通过程序员抛出
括号中可以不含参数,如果写上抛出异常时就会打印
注意点:
1 throw必须写在方法体内部,抛出异常的对象应该是Exception或者Exception子类对象;异常后面的代码不会执行
2 throw一般抛出的是自定义异常
处理异常
异常的处理有通常有两种形式,一种是声明异常,一种是try-catch捕获异常
异常的声明
当系统报出编译时异常,如果不想处理异常,那就要在该函数参数列表之后写出可能会报出的异常,throws后面可以报出多种异常,如果异常具有父子关系那么只需要写父类一场就可以了。当给这个方法声明异常之后,那该函数被调用时所在的函数就要处理异常(要么继续throws声明异常,最后交给JVM处理,JVM的处理结果就是异常终止,要么try-catch捕获异常)
这里有个 CloneNotSupportedException异常,当我们不抛出声明时,在编译的时候会报错
当我们声明异常之后,编译异常就没有了,但是我们并未处理,交给了JVM处理,系统就会报异常
注意不是所有编译异常都可以被处理,比如数组未初始化(因为没有对应的类),如图我们虽然声明了异常,但仍会报错
如果系统中有多个异常,那么一次只会抛出一个异常,不会一下子全部抛出
print()函数声明了一个异常,mian函数中使用了print(),因main必须处理这个异常(不处理就会编译异常无法运行),mian函数没有去捕获异常而是继续去声明,因此这个异常就交给了JVM处理,但是运行时发现系统并未报错,是因为throws只是声明异常,意思是这个方法可能会抛出异常,当这个函数在实际运行中并未抛出异常时,JVM也就不会异常终止。
try-catch捕获异常
try-catch格式特点
try不能单独存在后面可以单独加catch或finally;
func方法声明了异常,此时main函数没有继续去声明异常而是用try-catch捕获,当异常捕获成功就会执行catch中的语句,其中catch要传入一个异常类型和类型变量;变量名.printStackTrace即可打印异常位置,打印完之后程序正常执行,若catch没有捕捉到其括号内的异常类型则不会执行catch内的语句。
另外catch可以叠加写,也可以通过“|”写在一个catch中,又可以直接写一个Exception就涵盖了所有异常,推荐使用第一种,因为可以判断到底是那种异常
叠加写
注意的是上面的catch一定要是下面catch的子类(即先经过的catch语句的异常范围不能包含了后面catch中的异常,不然就没有意义了)
写一行
细节:变量名只写一个即可
try中代码发生异常后,try块异常后的代码就不执行了
异常有很多处理方式,要根据实际情况进行处理,并不是一定要捕获
Finally
语法:try{
}catch(){
}finally{}
语法中可以没有catch(){},但要写finally就一定要写try;
无论是否捕捉到异常finally都会执行,哪怕遇到return或者异常中止,也一定会在程序结束前执行finally中的代码
finally的作用是关闭资源,防止资源浪费,例如Scanner;
运行func结果为20,但在finally写return会报警告
try-catch处理异常总结
注意throw时抛出异常,throws是声明异常
自定义异常
因为有时候程序与运行可能不符合预期,所以我们会通过抛出异常来定位哪里的代码不符合预期。
实现代码:
我们先看系统中异常类的写法,然后仿照来写:
继承了一个类,并写了两个构造方法
注意这里的自定义异常可以继承两个类 Exception(继承后默认是受查异常) 或者 RuntimeException(非受查异常)
案例
我们来自定义个密码异常和用户名异常,当用户名不对或者密码不对可以捕获异常
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String adimn = scanner.nextLine();
String password = scanner.nextLine();
try{Log log = new Log();
log.log(adimn,password);
}catch (AdminException a){
a.printStackTrace();
System.out.println("adminException");
}catch (PassWordException a){
a.printStackTrace();
}finally {
scanner.close();
}
System.out.println("over");
}
}
展示了关键代码,其中要知道抛出异常的格式;自定义异常的方法(仿照系统中的异常写,除了继承的类可以不一样,其他都一样);再者就是运用异常的思想,写个方法不符合就throw.