异常 :指的是程序在执行过程中或编译过程中出现了问题,最终会导致JVM的非正常停止
异常的根类是java.lang.Throwable ,其下有两个子类:
java.lang.Error
java.lang.Exception 这个就是我们平时说的异常
Throwable体系:
Error:严重错误Error,无法通过处理的错误,只能事先避免。
Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。
Exception又分为编译时异常和运行时异常,文末会阐述区别
当出现异常时,若未作任何处理,则异常则会抛给方法的调用者,一直到JVM处理
例:
在test()方法中出现了ArrayIndexOutOfBoundsException异常
可是方法调用者main方法没有对异常进行处理
则main又会将异常抛给方法调用者也就是JVM
public static void main(String[] args) {
test();
}
public static void test() {
int[] arr = {1, 2, 3, 4};
System.out.println(arr[5]);
}
结果:
JVM就会将异常类型、异常信息、出现位置等信息打印在控制台,并结束程序运行
格式:
try{
//可能出现异常的代码
}catch(异常类型 变量名){
//处理异常的代码
}finally{
//无论try块中是否有异常,均实现的代码
}
注意事项:
1.try块中出现异常直接被catch块捕获,不执行剩下的try代码
2.try块中出现了与catch()指明的异常类型匹配,才会执行catch代码块中的代码
3.catch()代码块指明的异常类型可以有多个,匹配try的异常类型顺序是从上到下
4.finally代码块无论try代码块中是否存在异常都会运行
5.Exception是所有异常的父类,若不清楚出现异常的具体类名,可在catch后使用(Exception e)捕获所有异常
public void printStackTrace() 在控制台打印异常的详细信息
try {
int[] arr = {2, 56, 37, 34, 22};
System.out.println(arr[6]);
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace
public String getMessage() 获取发生异常的信息
try {
int[] arr = {2, 56, 37, 34, 22};
System.out.println(arr[6]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage()); //输出:6
}
public String toString() 获取异常的类型和异常描述信息(不常用)
try {
int[] arr = {2, 56, 37, 34, 22};
System.out.println(arr[6]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.toString()); //输出:java.lang.ArrayIndexOutOfBoundsException: 6
}
格式:
throw new 异常类名("异常信息")
前提:
先作好异常出现的if判断,然后创建异常类型对象,并抛出
抛出一个异常对象,给方法调用者,并且结束当前方法的运行
public static void main(String[] args) {
test(5);
}
public static void test(int num) {
int[] arr = {2, 56, 37, 34, 22};
if (num > 0 && num < 5) {
System.out.println(arr[num]);
} else {
throw new ArrayIndexOutOfBoundsException("抛出的异常信息");
}
}
上述代码中,主方法调用test()方法时传递了整数5,会导致数组越界异常
事先写好的if语句判断,将越界异常的信息抛回给调用方法的主方法
主方法没有对异常进行任何处理
所以又会抛给JVM处理,打印异常类型、信息并且结束程序运行
异常中分为编译时异常和运行时异常两大类
可自行查找API文档,只要该异常是RuntimeException或者是他的任意子类,则该异常便是运行时异常
1.方法体中抛出运行时异常,方法上不需要throws声明抛出
2.调用了声明抛出运行时异常的方法,也可以不作处理
(因为运行时异常可以通过开发人员良好的编程习惯避免)
例:
int[] arr = {1,2,3};
int index = 3;
if (index >= 0 && index < arr.length){
System.out.println(arr[index]);
}
1.除了运行时异常,其他的异常都是编译时异常
2.方法体内部中抛出编译时异常且没有被捕获处理时,方法必须要用throws声明抛出
3.调用了声明抛出编译时异常类型的方法,调用者必须作处理(抛出或捕获)
因为这类异常都无法通过代码来避免,代码无法判断该文件是否真实存在
public void test() {
File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f); //开发工具提示编译错误!!
}
}
所以要求开发者自行对异常进行处理(捕获或抛出),并且声明throws抛出
public void test() throws IOException{
File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f); //不作处理默认抛给方法调用者处理
}
}
这里也就学到了一个新的关键字throws,用于告知方法调用者本方法体中可能存在异常的可能
让方法调用者作好处理异常的准备
格式:
修饰符 返回值 方法名(参数) throws 异常类名,.....
存在多种异常可以用,隔开写多种异常类名
也可以直接写Exception抛出所有异常