java异常处理简析

1- try

将可预见可能抛出异常的代码包含在try语句块中,也就是将一些会抛出异常的方法调用放在这个语句块,以便后续处理

2- 异常

  1. Throwable

错误和异常的超类(Error和Exception都继承自Throwable),包含了其线程创建时线程执行堆栈的快照,通过printStackTrace()方法打印堆栈跟踪数据信息。

  1. Exception

被检查异常的顶级类,** 除了RuntimeException ,Exception类型的异常编译器会检查这种异常,需要对应的异常处理 **,否则会因为异常抛出导致程序异常终止,我们在开发的时候主要就是捕获这种异常。

  1. RuntimeException

** 运行时被检查异常,继承自Exception,但是这种异常发生在虚拟机运行期间,编译器不会检查这种异常 ,如果我们调用的方法可能抛出RuntimeException 类型的异常,但是并没有相应的try/catch进行处理,最后能通过编译,是因为编译器并不会在编译期间对这种异常进行检查。 如果代码会产生RuntimeException,则需要调整代码进行避免 **,如 ** ArithmeticException **

  1. Error

继承自Throwable,** 编译器不会对错误进行检查 **。用于指示严重错误的发生,说明已经发生了无法挽回的错误,程序无法修复这种错误,直接导致程序因为错误而终止。如 ** VirtualMachineError **

** 下面重点介绍Exception类型的常用异常 **

以下都是Exception的子类,表示特定的用途

  1. IllegalArgumentException 参数的值不合适
  2. IllegalStateException 参数的状态不合适
  3. NullPointerException 在null被禁止的情况下参数值为null
  4. IndexOutOfBoundsException 下标越界
  5. ConcurrentModificationException 在禁止并发修改的情况下,对象检测到并发修改
  6. UnsupportedOperationException 对象不支持客户请求的方法

3- catch

捕获try语句块中的Exception异常,并进行相应的处理
1)编译的时候有些异常的捕获,如Exception,IllegalStateException,NullPointerException等(java.lang包的异常)并不要求try语句中含有抛出异常的方法调用;
2)但是有些异常的捕获如ObjectStreamException,IOException等(java.io包的异常)并要求try语句中必须含有抛出异常的方法调用,否则编译错误

  1. 一个try语句块可以有多个catch子句来捕获不同的异常,但是** 同时只能捕获一个异常, 在异常发生的代码段,后续的代码得不到执行 **,转而执行对应的catch子句,并正常退出方法的调用。
    例子如下:
例子1
  1. 通过捕获异常的超类来捕获
    例子如下:
例子2
  1. catch中如果没有捕获到抛出的异常,则继续向上级调用者抛出异常
    例子如下:
例子3

4- throw 和 throws

** throw **

用于在方法体内抛出异常,如果方法内部抛出异常,则此方法声明上可以通过throws声明抛出的异常,也可以什么都不声明,对抛出的异常并没有什么影响。
比如


例子4

** throws **

用于方法声明上,声明可能抛出的异常,见例子4

需要注意的是异常声明在继承时多态隐含的关系(** 对父类方法进行方法重写 ),虽然 异常声明不是方法签名的一部分 **

  1. ** 如果父类的方法没有声明抛出异常,子类覆盖的方法也不能声明抛出任何异常。**
  2. ** 如果父类的方法声明抛出特定异常E,子类覆盖的方法要么不声明抛出任何异常,要么声明抛出E异常或者E异常的子类(隐含的继承关系)。**

5- finally

表示的不管try方法块是正常执行完毕,还是抛出异常退出try语句块,finally都会在程序离开try语句块后执行,用来做最后的资源回收等操作。

  1. ** try中的return,catch中的return,finally中的return **
例子5

从中可以看出finally的return最终会覆盖try中的return语句,catch中没有捕获到异常,没有得到执行,** finally > catch > try 按照等级对return进行覆盖 **。

  1. ** try中的System.exit() **
例子6

** 当try执行System.exit(0/1)都将立马退出程序,finally中的内容是得不到执行的。 **

  1. 守护进程中的finally

守护进程与finally

  1. ** try/finally组合 **

例子7

setObj方法抛出异常,tryFinally方法调用setObj,并没有捕获异常,而是由tryFinally上级调用main方法来捕获,但是如果main方法没有捕获,则会因为异常抛出而没有处理而异常终止程序,参见AQS的acquireQueued方法

总结

避免将异常处理用于流程控制,也不能频繁的检查捕获不必要的异常,因为频繁异常的捕获和抛出(获取抛出异常线程的堆栈信息等操作)将消耗大量的系统性能,而且抛出的异常应尽量使用标准的异常类,来做到明确表达异常的含义。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 通俗编程——白话JAVA异常机制 - 代码之道,编程之法 - 博客频道 - CSDN.NEThttp://blog...
    葡萄喃喃呓语阅读 3,224评论 0 25
  • Java异常类型 所有异常类型都是Throwable的子类,Throwable把异常分成两个不同分支的子类Erro...
    予别她阅读 977评论 0 2
  • 初识异常(Exception) 比如我们在取数组里面的某个值得时候,经常会出现定义的取值范围超过了数组的大小,那么...
    iDaniel阅读 1,899评论 1 2
  • 有朋友三年前就推荐这个电影给我,但是一直没有看。为了交剪辑群影评,终于打开了这部电影。 看到电影名,七号房的礼物,...
    小饼干310阅读 851评论 0 1
  • 1. 感恩猴年一切顺顺利利。 2. 感恩准备早餐的素食档。 3. 感恩带来特别讯息的陌生大哥。 4. 感恩可以看到...
    jaychua阅读 112评论 0 0