Java异常处理机制
主要关键字: try、catch、finally、throw、throws
2.1、try -catch 对异常进行捕捉和处理
方式:可能出现异常的代码放入try 语句块中,使用catch 语句块捕获异常。
try {
// 可能发生异常的语句 catch 中传递的参数,可以是异常父类,也可以是具体异常
} catch(ExceptionType e) {
// 处理异常语句
}
可能出现的情况:
A、try语句块中所有的语句正常执行完毕,没有异常,那么catch 语句块中的所有语句被忽略
B、try语句块在执行时发生异常,并且与catch语句块中声明的异常类型匹配,那么try 语句块中剩下的代码将 被忽略,执行catch语句块中的内容。
匹配指的是catch 所处理的异常类型与所生成的异常类型完全一致或是他的父类。
C、try语句块在执行时发生异常,但是与catch 语句块中声明的异常类型不匹配,方法立刻退出。
//输出异常
System.err.println();
//异常对象的方法
void printStackTrace()
String getMessage()
void printStackTrace():输出异常堆栈信息。
堆栈信息包括程序运行当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用序列。
String getMessage():返回异常信息描述字符串,该字符串描述了异常产生的原因,是printStackTrace() 输出信息的一部分。
!!!
如果try 中的语句发生异常,那么语句中剩下的代码会被忽略,系统会自动生成相应的异常对象包括异常类型、异常出现时的运行状态以及对该异常的详细描述。如果该异常与catch 中声明的匹配,就会把该异常对象赋予给catch 后面的异常参数,相应的catch语句块被执行。
2.2、使用try - catch- finally 处理异常
特点:无论是否发生异常 finally 语句块的内容都会被执行
try {
// 可能会发生异常的语句
} catch(ExceptionType e) {
// 处理异常语句
} finally {
// 清理代码块
}
a、如果try 语句块中所有语句正常执行完毕,finally语句块也会被执行。
b、如果try语句块在执行过程中发生异常,无论这种异常能否被catch语句块捕获到,都将执行finally语句块中的代码
c、try-catch-finally 结构中try 语句块是必须存在的,catch、finally 语句块为可选的,两者至少出现其一
d、即使在catch 语句块中使用return语句,finally 语句块中的内容也会执行,执行对顺序是,先执行catch 语句块中return之前的语句,在执行finally中对语句,最后执行return 语句退出。
e、finally 语句块中不执行的唯一情况是在异常处理代码中执行了 System.exit(1)退出了虚拟机。
package com.obge.ex; import java.util.Scanner; public class Testt { public static void main(String[] args) { try { Scanner in= new Scanner(System.in); System.out.println("请输入被除数:"); int num1 = in.nextInt(); System.out.println("请输入除数:"); int num2 = in.nextInt(); //输出格式控制 System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2)); }catch(Exception e) { //错误提示红色字体 System.err.println("出现错误:除数为0"); //打印错误原因 System.out.println(e.getMessage()); //不执行finally语句 System.exit(1); }finally { System.out.println("感谢使用本程序!"); } } }
2.3、使用多重catch 处理异常
由于一段代码可能引发多种类型的异常,所以使用一个try语句后跟着多个catch 语句块,分别处理不同异常。
顺序:从子类到父类,最后一个一般是 Exception 类,如果 Exception 类放到前面,后面的catch语句就不会执行了。
运行时:系统从上到下分别对每个catch语句块处理的异常类型进行检测,并执行第一个与异常类型匹配的catch语句,执行其中一条语句后,后面对catch语句将被忽略。
语法格式:
try {
逻辑程序块
} catch(ExceptionType1 e) {
处理代码块1
} catch (Exception e) {
处理代码块2
} finally {
释放资源代码块
}
2.4、使用throws声明抛出异常
throws:throws声明该方法体中未知的异常,交给上一级调用者处理
特点:
声明某个方法可能抛出的各种异常以通知调用者。
可以同时声明多个异常,之间使用逗号隔开
主要方式:
A、通过try-catch 捕获并处理异常
B、通过throws继续声明异常, 如果调用者不知如何处理该异常,可以继续通过throws 声明异常,让上一级调用者处理。
C、main() 方法声明的异常由Java虚拟机来处理,JVM 对异常的处理方法是,打印异常的跟踪栈信息,并中止程序运行,这就是前面程序在遇到异常后自动结束的原因。
格式:
访问修饰符 返回值类型 方法名(参数列表) throws Exception 1,Exception2,…{
…
}
代码:
首先在定义 readFile() 方法时用 throws 关键字声明在该方法中可能产生的异常,然后在 main() 方法中调用 readFile() 方法,并使用 catch 语句捕获产生的异常。
import java.io.FileInputStream; import java.io.IOException; public class Test04 { public void readFile() throws IOException { // 定义方法时声明异常 FileInputStream file = new FileInputStream("read.txt"); // 创建 FileInputStream 实例对象 int f; while ((f = file.read()) != -1) { System.out.println((char) f); f = file.read(); } file.close(); } public static void main(String[] args) { Throws t = new Test04(); try { t.readFile(); // 调用 readFHe()方法 } catch (IOException e) { // 捕获异常 System.out.println(e); } } }
!!!!
方法重写时声明抛出异常的限制
使用 throws 声明抛出异常时有一个限制,是方法重写中的一条规则:子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出的异常多。
2.5、使用throw 抛出异常
解决系统无法自动发现并解决的异常,使用throws 来自行抛出异常,比如:年龄不再正常范围内,性别不是男或女等
格式:
//在方法中直接抛出一个异常 throw new ExceptionObject ExceptionObject:必须是 Throwable 类或其子类的对象。如果是自定义异常类,也必须是 Throwable 的直接或间接子类。
代码:
package com.obge.obj; public class Student{ private String gender = "男"; //设置性别 public void setGender(String gender) throws Exception{ if("男".equals("男")|| "女".equals("女")) { this.gender = gender; }else { //抛出异常 throws new Exception("冷静,性别只有男女!!!"); } } }
mian(){
Student stu = new Student;
try{
stu.setGender("obge");
}catch(Exception e){
e.printStackTrace();
}
}
2.6、自定义异常
当JDK 的异常类型不能满足程序需求是可以自定义异常类。
常用步骤:
A、定义异常类,并继承Exception 或者 RunntimeException
B、编写异常类的构造方法,并继承父类实现,
//常见的构造方法有以下四种形式 //无参构造 public MyException() { super(); } //有参构造 public MyException(String message,Throwable cause) { super(message,cause); } public MyException(String message) { super(message); } public MyException(Throwable cause) { super(cause); }
C、实例化自定义异常对象,并在程序中抛出
格式:
访问修饰符 class 异常名 extends Exception{ //构造方法 }
2.7、异常链
解决A 方法B方法,B 方法却抛出了异常。
重要:
1、throws 与 throw 的区别
a、作用不同:throw 用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常
b、使用的位置不同: throw位于方法体内部,可以作为单独语句使用;throws 必须跟在方法参数列表的后面,不能单独使用。
c、内容不同:throw 抛出一个异常对象,只能是一个;throws后面跟异常类,可以是多个