Java异常略解

本文详细介绍了Java异常处理机制,包括异常的获取、try-catch-finally结构、异常类的层次结构及其用法。通过实例解析了如何捕获和处理异常,以及异常类的分类,如RuntimeException、IOException等。强调了finally块在异常处理中的作用,无论是否发生异常,finally块总会执行。
摘要由CSDN通过智能技术生成

Java异常略解

异常就是程序运行时可能产生的某种特殊情况,通过异常处理可以改变程序的控制流程,让程序能对错误做出处理。

1.获得异常信息

异常对象调用如下方法得到或输出有关异常的信息:

  1. public String getMessage();
  2. public void printStackTrace();
  3. public String toString();

2.try-catch-finally

将可能出现异常的操作放在try部分,当try部分抛出异常对象或调用一个可能抛出异常对象的方法且该方法抛出了异常对象,那么执行相应的catch部分。无论是否发生异常,总是执行finally部分。

一般形式如下:

try{
	try块中放可能发生异常的代码;
    如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码(如果有的话);
    如果发生异常,则尝试去匹配catch;
}
catch(ExceptionSubClass1 e){
	每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch;
    catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常;catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问;
    如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部调用者中去匹配异常处理器;
    如果当前try块发生异常,且匹配的catch块中处理异常时也抛出异常,那么后面的finally也会执行,然后去外围调用者中寻找合适的catch;
    如果try中没有发生异常,则所有的catch块将被忽略;
}
catch(ExceptionSubClass2 e){
	如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义;
}
finally{
	finally块通常是可选的。
	无论异常是否发生,异常是否匹配被处理,finally都会执行。
	一个try至少要有一个catch块,否则, 至少要有1finally块。但是finally不是用来处理异常的,finally不会捕获异常。
	finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。 
}

3.异常类

Throwable Exception Error VirtulMachineError AWTError StackOverFlowError OutOfMemoryError IOException RuntimeException EOFException FileNotFoundException 可处理 不可处理 虚拟机运行错误 AWT错误 栈溢出 内存溢出 读写异常 运行异常 文件结束异常 找不到文件异常
RuntimeException ArrithmeticException MissingResourceException ClassNotFoundException NullPointerException IllegalArgumentException ArrayIndexOutOfBoundsException UnknownTypeException 除数为0异常 找不到资源异常 找不到类异常 使用空指针异常 非法传参异常 数组索引越界异常 未知形式异常
UncheckedException Error RuntimeException CheckedException OtherExceptions

Unchecked Exception 与 Checked Exception 是对于javac而言的。

  • Unchecked Exception

javac在编译时,不会提示和发现这样的异常。对于这些异常,我们应该修正代码,而不是去通过异常处理器处理 。这样的异常发生的原因多半是代码错误。

  • Checked Exception

javac强制要求程序员为这样的异常做预备处理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。

  • 处理机制

异常是在执行某个方法时引发的,且当一个方法发生了异常,该方法的调用者也会被异常影响。当这些被影响的方法以异常信息输出时,就形成的了异常追踪栈。异常最先发生的地方,叫做异常抛出点。
异常从被调用方法(栈顶)向调用方法(栈底)回溯,叫做异常的冒泡。异常的冒泡是为了在当前发生异常的方法或者这个方法的调用者中找到最近的异常处理程序。若没有特别的处理,则交由JRE处理,程序终止。若有处理,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。这种策略叫做终结式异常处理模式。

  • throws函数声明

如果一个方法内部的代码会抛出Checked Exception,而方法自己又没有完全处理掉,则javac保证必须在方法的签名上使用throws关键字声明这些可能抛出的异常,否则编译不通过。
throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。
当子类重写父类的带有 throws声明的函数时,其throws声明的异常必须在父类异常的可控范围内,即用于处理父类的throws方法的异常处理器,必须也适用于子类的这个带throws方法 ,这是为了支持多态。
采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。

一般形式如下:

public void F() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN
{ 
     F内部可以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的子类的异常对象。
}
  • throw 异常抛出

可以通过throw语句手动显式的抛出一个异常。throw语句的后面必须是一个异常对象。
throw 语句必须写在方法中,执行throw 语句的地方就是一个异常抛出点,它和由JRE自动形成的异常抛出点没有任何差别。

一般形式如下:

public void F()
{
	throw new Exception(或其子类)("Message"); 
}
  • 自定义异常

如果要自定义检查异常类,则扩展Exception类。如果要自定义非检查异常类,则扩展RuntimeException类。
要求至少满足下列其中一条:

  • 包含一个无参构造函数
  • 包含 一个带有String参数的构造函数,并传递给父类的构造函数。
  • 包含一个带有String参数和Throwable参数,并都传递给父类构造函数
  • 包含一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

4.finally语句与return

  • finally语句不被执行的条件
  1. try语句没有被执行。
  2. try块中出现System.exit(0);之类语句。
  • finally块语句与try-catch块中return语句的执行顺序
  1. finally块语句在try-catch块中return语句执行(计算出返回值【注:若返回值为变量,则此变量切实被修改】)之后,返回结果之前执行(若多次return,只在最终的返回结果之前执行)。
  2. finally块中修改语句可能会影响try-catch块中已经确定的返回值。
  3. finally块中若有return语句,将会覆盖try-catch块中的return语句返回。且导致finally块之后的语句不可达。
  4. finally块中若有异常,将会覆盖try-catch块中的异常。
  5. 发生异常后catch块中return语句执行情况与未发生异常的try块中return语句执行情况完全一致。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值