Thinking in java: 异常处理(2)

本文深入探讨Java异常处理机制,包括异常声明、捕获、finally块的使用及异常限制。讲解了如何通过throws关键字声明可能抛出的异常,RuntimeException的特殊处理,以及如何使用finally确保资源的正确释放。

异常说明

  • java强制让函数名后面接上throws+异常类型明示这个方法可能抛出的所有异常类型,比如f()中可能在某些判断体内会有TooBig, TooSmall, DivZero这些类型的异常,那么代码在实现的时候,就需要加上
	void f() throws TooBig, TooSmall, DivZero{...}
  • 只有RuntimeException类型的异常是可以不显示表示的
  • 如果f()潜在一些异常,但是却没有被告知,那么f()将会被编译器提醒要检查异常
  • 可以在异常说明中写上该方法可能不会抛出的异常,这一般出现在派生类和接口的定义中,为的是让继承类不用修改已有的办法

捕获所有异常

  • catch(Exception e),将绝大多数异常类型的基类Exception写道形参中即可, 这个捕获一般是放到最后来捕获遗漏的异常。
  • Exception继承自Throwable基类,含有方法:
    • String getMessage():返回详细信息
    • String getLocalizeMessage():返回本地详细信息
    • String toString():返回类型简单描述
    • void printStackTrace():默认输出到System.err
    • void printStackTrace(PrintStream): 输出到如System.out输出对象
    • void printStackTrace(java.io.PrintWriter):输出到PrintWriter对象
    • Throwable fillInStackTrace():在对象内部记录栈帧当前状态,用于重新抛出错误,得到接住这个异常的方法不会记录这个异常抛出点之前的异常抛出点
    • getStackTrace(): 返回一个由栈轨迹元素构成的数组,栈顶(数组第一个元素)是最后调用的函数,栈底(数组最开始的元素)是调用序列的第一个函数

异常链

  • 捕获一个异常之后,接着抛出另一个异常,希望把原始的异常信息保存下来
  • Throwable子类构造器可以接受一个cause对象作为参数,该对象用于表示原始的异常。
  • 只有三个Throwable的子类拥有带cause的构造器,分别是Exception, RuntimeException和, Error
  • 想要将所有类型的异常的形成异常链,需要用initCause()方法而不是构造器

JAVA标准异常

  • 两大类:ErrorException,一般不用关心Error类型,Exception才是程序员可以主动抛出的
  • 除了java.lang之外,还有util, net, io包中由定义的异常
  • 特殊异常RuntimeException:如NullPointerException,一般而言是JVM中实现的。RuntimeException的捕获可以不屑异常说明,输出会直接发送给System.err,而且RuntimeException可以不用显式写在try块中进行捕获,如果没有捕获,会直达main函数,并且在程序结束前调用printStackTrace()

finally

  • 异常捕获三剑客的最后一个模块:无论有没有抛出异常,finally都会执行
  • finally的作用:保证try中无论发生了什么,在finally中都能进行对象的释放,不过这个保障对于有GC的语言来说没有那么吸引人。
  • 对于java而言, 要把除内存之外的资源恢复到初始状态,或者最终想要保持的状态,可以考虑使用finally
  • finally的作用范围:即便在try中进行了break, continue, return等操作,finally也一定会执行。
  • finally 导致的异常丢失(JDK 1.5,后续版本不知道会不会这样):唉卡在嵌套try中,try中的异常被finally中的异常覆盖
class importantException extends Exception{
	public String toString(){
		return "A very important Exception";
	}
}
class HoHumException extends Exception{
	public String toString(){
		return "A trivial Exception";
	}
}

public class LostMessage{
	void f() throws importantException {
		throw new importantException();
	}
	void g() throws HoHumException{
		throw new HoHumException();
	}
	public static void main(String[] args){
		try{
			try{
				LostMessage lm = new LostMessage();
				try{
					lm.f();
				}finally{
					lm.g();
				}
			}catch(Excetpion e){
				System.out.println(e);
			}
		}
	}
}
// output: A trivial exception

异常限制

  • 在子类继承基类的时候,只能抛出在基类方法的异常说明里面的样式,这确保了基类代码应用到派生类对象的时候,一样能够工作

异常匹配机制

  • 抛出异常之后,异常处理系统会按照书写顺序找到最近的捕获语句,一旦匹配到,处理系统就默认异常已经处理完毕,不再往下寻找。
  • 异常匹配机制要求,书写代码的时候,子类异常一定要位于基类异常的前面,不然由于向上转型的原因,会导致子类异常永远无法被捕获。

参考

  • 《JAVA编程思想》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值