1、异常处理
运行时异常可以通过规范的代码进行规避
受检异常必须进行预处理,否则出现编译报错
2、受检异常有两种预处理方式
1.异常捕获处理
try{
对可能产生异常的代码进行监视
如果 try 代码块的某条语句产生了异常,就立即跳转到 catch 子句执行,try 代码块后面的代码块不再执行
try 代码块可能有多个受检异常需要预处理,可以通过多个 catch 子句分别捕获
}catch(异常类型1 e1){
捕获异常类型1的异常,进行处理
在开发阶段,一般的处理方式要么获得异常信息,要么打印异常栈跟踪信息
例:e1.printStackTrace();
在部署之后,如果有异常,一般把异常信息打印到日志文件中
}catch(异常类型2 e1){
捕获异常类型2的异常,进行处理
如果捕获的异常类型有继承关系,应该先捕获子异常,再捕获父异常,如果没有继承关系,catch 子句没有先后顺序
}finally{
不管是否产生异常,finally 子句总是会执行
一般情况下,会在 finally 子句中释放系统资源
}
演示:
处理单个异常:
鼠标移至红色波浪线出,点击第二条语句即可自动生成try/catch语句
执行下列代码之前可先观看javaSE进阶学习记录:3.2 运行时异常 与 3.3 受检异常(编译时异常)
package com.LearnTest02.D02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
* 演示异常捕获预处理
*/
public class ExceptionClass03 {
public static void main(String[] args) {
try {
System.out.println("try代码块中有语句产生了受检异常需要预处理");
FileInputStream fis = new FileInputStream("e:/1.txt");//有FileNotFoundException异常需要预处理
System.out.println("如果try代码块某条语句在运行时产生了异常,就跳转到catch子句执行");
} catch (FileNotFoundException e) {
//捕获FileNotFoundException异常,在执行时,如果产生了这个异常,如何处理
//在开发时,一般的处理方式就是打印异常信息
e.printStackTrace();
}
System.out.println("main 结束");
}
}
运行结果:
根据结果发现,程序没有被中断,如果没有预处理,则程序中断
对异常进行处理后,在程序运行过程中,即使出现了异常,程序也不会中断,继续向下执行,这就是异常预处理的作用
异常预处理可以提高程序的健壮性(鲁棒性,robust)
处理多个异常:
使用第二条语句进行添加 catch 子句
package com.LearnTest02.D02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 演示异常捕获预处理
*/
public class ExceptionClass03 {
public static void main(String[] args) {
try {
System.out.println("try代码块中有语句产生了受检异常需要预处理");
FileInputStream fis = new FileInputStream("e:/1.txt");//有FileNotFoundException异常需要预处理
System.out.println("如果try代码块某条语句在运行时产生了异常,就跳转到catch子句执行");
System.out.println("try代码快可能有多个受检异常需要预处理,可以通过多个catch子句分别捕获");
fis.read();//读取文件的内容,有IOException受检异常需要处理
} catch (FileNotFoundException e) {
//捕获FileNotFoundException异常,在执行时,如果产生了这个异常,如何处理
//在开发时,一般的处理方式就是打印异常信息
e.printStackTrace();
} catch (IOException e) {
//FileNotFoundException继承了IOException,这两个异常有继承关系,应该先捕获子异常再捕获父异常
//如果两个 catch 位置调换,则子异常永远无法被捕获到
e.printStackTrace();
}
System.out.println("main 结束");
}
}
运行结果自行尝试
2.throws 抛出处理
package com.LearnTest02.D02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
* throws抛出处理
* 在方法体中如果有受检异常需要预处理,可以捕获预处理,也可以抛出预处理
*/
public class ExceptionClass05 {
//main方法抛出的异常JVM负责处理,JVM的处理方式就是中断程序,打印异常信息
public static void main(String[] args) throws FileNotFoundException {
System.out.println("main方法中,调用m1方法");
m1();
System.out.println("main方法结束");
}
//再抛出,谁调用m1()方法,谁处理
private static void m1() throws FileNotFoundException {
System.out.println("m1方法中,调用m2方法");
m2();
System.out.println("m1方法结束");
}
//在定义m2()方法时,声明抛出了一个异常,谁调用m2()方法谁负责处理该异常
private static void m2() throws FileNotFoundException {
System.out.println("m2方法调用FileInputStream构造方法");
FileInputStream fis = new FileInputStream("d:/1.txt");
System.out.println("m2方法结束");
}
}
输出结果为:
当在m1()方法进行捕获预处理时
package com.LearnTest02.D02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
* throws抛出处理
* 在方法体中如果有受检异常需要预处理,可以捕获预处理,也可以抛出预处理
*/
public class ExceptionClass05 {
//main方法抛出的异常JVM负责处理,JVM的处理方式就是中断程序,打印异常信息
public static void main(String[] args){
System.out.println("main方法中,调用m1方法");
m1();
System.out.println("main方法结束");
}
//在m1()方法中进行捕获预处理
private static void m1(){
System.out.println("m1方法中,调用m2方法");
try {
m2();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("m1方法结束");
}
//在定义m2()方法时,声明抛出了一个异常,谁调用m2()方法谁负责处理该异常
private static void m2() throws FileNotFoundException {
System.out.println("m2方法调用FileInputStream构造方法");
FileInputStream fis = new FileInputStream("d:/1.txt");
System.out.println("m2方法结束");
}
}
输出结果为:
程序没有中断
throw抛出处理总结:
在定义方法时,如果方法体有 受检异常 需要预处理,可以捕获异处理,也可以抛出处理,谁调用这个方法,谁负责处理异常
在定义方法时,把异常抛出就是为了提醒方法的使用者,有异常需要预处理
3、在处理异常时,是选择捕获处理还是抛出处理?
1.一般情况下,在调用其他方法时,如果被调用的方法有受检异常需要预处理,选择捕获处理
2.在定义方法时,如果方法体中有受检异常需要预处理,可以选择捕获处理也可以选择抛出处理,如果方法体中通过 throws 语句抛出了一个异常对象,所在的方法应该使用 throws 声明该异常