疯狂Java讲义-异常处理

本文详细介绍了Java的异常处理机制,包括try...catch、finally、throw和throws的使用,异常类的继承体系,Java7的新特性,以及Checked异常和Runtime异常的区别。强调了异常处理的重要性,提供最佳实践,如避免过度使用异常,合理划分try块,避免使用Catch All语句,以及不要忽略捕获到的异常。
摘要由CSDN通过智能技术生成

异常处理

本章思维导图

异常处理

Java的异常处理机制主要依赖于try、catch、finally、throw和throws五个关键字,其中try关键字后紧跟一个花括号括起来的代码块(花括号不可省略),简称try块,它里面放置可能引发异常的代码。catch后对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块。多个catch后还可以跟一个finally块,finally块用于回收在try块里打开的物理资源,异常机制会保证finally块总被执行。throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常;而throw用于抛出一个实际的异常,throw可以单独作为语句使用,抛出一个具体的异常对象。

Java7进一步增强了异常处理机制的功能,包括带资源的try语句、捕获多异常的catch两个新功能。

Java将异常分为两种,Checked异常Runtime异常,Java认为Checked异常都是可以在编译阶段被处理的异常,所以它强制程序处理所有的Checked异常;而Runtime异常则无须处理。Checked异常可以提醒程序员需要处理所有可能发生的异常。

异常处理机制

Java的异常处理机制可以让程序具有极好的容错性,让程序更加健壮。当程序运行出现意外情况时,系统会自动生成一个Exception对象来通知程序,从而实现将“业务功能实现代码”和“错误处理代码”分离,提供更好的可读性。

使用try…catch捕获异常

Java异常处理机制的语法结构。

try {
   
    // 业务实现代码
    ...
} catch (Exception e) {
   
    // 错误处理代码
    ...
}

如果执行try块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给Java运行时环境,这个过程被称为抛出(throw)异常。

当Java运行时环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的catch块则把异常对象交给该catch块处理,这个过程称为捕获(catch)异常;如果Java运行时环境找不到捕获异常的catch块,则运行时环境终止,Java程序也将退出。

不管程序代码块是否处于try块中,甚至包括catch块中的代码,只要执行该代码块时出现了异常,系统总会自动生成一个异常对象。如果程序没有为这段代码定义任何的catch块,则Java运行时环境无法找到处理该异常的catch块,程序就在此退出。

异常类的继承体系

异常类之间的继承关系

每个catch块都是专门用于处理该异常类及其子类的异常实例。

当Java运行时环境接收到异常对象后,会依次判断该异常对象是否是catch块后异常类或其子类的实例,如果是,Java运行时环境将调用该catch块来处理异常;否则再次拿该异常对象和下一个catch块里的异常类进行比较。

try块后的花括号({…})不可以省略,catch块后的花括号({…})也不可以省略。try块里声明的变量是代码块内局部变量,它只在try块内有效,在catch块中不能访问该变量。

Java把所有的非正常情况分为两种:异常(Exception)和错误(Error),它们都继承Throwable父类。

Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,这将导致应用程序中断。通常应用程序无法处理这些错误,因此应用程序不应该试图使用catch块来捕获Error对象。在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类。

Java运行时的异常处理逻辑可能有如下几种情形。

  • 数组越界异常,Java运行时将调用IndexOutOfBoundsException对应的catch块处理异常。
  • 数字格式异常,Java运行时将调用NumberFormatException对应的catch块处理异常。
  • 算术异常(例除0异常),Java运行时将调用AritheticException对应的catch块处理该异常。
  • 如果程序运行时出现其他异常,该异常对象总是Exception类或其子类的实例,Java运行时将调用Exception对应的catch块处理该异常。
  • 当试图调用一个null对象的实例方法或实例变量时,就会引发NullPointerException异常,Java运行将会调用对应的catch块来处理该异常。

总是把对应Exception类的catch块放在最后,实际上,进行异常捕获时不仅应该把Exception类对应的catch块放在最后,而且所有父类异常的catch块都应该排在子类异常catch块的后面,即先处理小异常,再处理大异常,否则将出现编译错误。

Java7新增的多异常捕获

在Java7以前,每个catch块只能捕获一种类型的异常;但从Java7开始,一个catch块可以捕获多种类型的异常。

使用一个catch块捕获多种类型的异常时需要注意如下两个地方。

  • 捕获多种类型的异常时,多种异常类型之间用竖线(|)隔开。
  • 捕获多种类型的异常时,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值。
public class MultiExceptionTest {
   
	public static void main(String[] args) {
   
		try {
   
			int a = Integer.parseInt(args[0]);
			int b = Integer.parseInt(args[1]);
			int c = a / b;
			System.out.println("您输入的两个数相除的结果是: " + c);
		} catch(IndexOutOfBoundsException | NumberFormatException | ArithmeticException ie) {
   
			System.out.println("程序发生了数组越界、数字格式异常、算术异常之一");
			// 捕获多异常时,异常变量默认有final修饰
			// 所以下面代码有错
			ie = new ArithmeticException("test");
		}
	}
}

访问异常信息

如果程序需要在catch块中访问异常对象的相关信息,则可以通过catch块的后异常形参来获得。当Java运行时决定调用某个catch块来处理该异常对象时,会将异常对象赋给catch块后的异常参数,程序即可通过该参数来获得异常的相关信息。

所有的异常对象都包含了如下几个常用方法。

  • getMessage():返回该异常的详细描述字符串。
  • printStackTrace():将该异常的跟踪栈信息输出到标准错误输出。
  • printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定输出流。
  • getStackTrace():返回该异常的跟踪栈信息。
public class AccessExceptionMsg {
   
	public static void main(String[] args) {
   
		try {
   
			FileInputStream fis = new FileInputStream("a.txt");
		} catch (IOException ioe) {
   
			System.out.println(ioe.getMessage());
			ioe.printStackTrace();
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值