Java异常处理

Java异常处理

错误处理

错误

在计算机程序执行的过程中,错误总会出现:

l  用户输入错误

l  读写文件错误

l  网络错误,内存耗尽,无法连接打印机

 

如果方法调用出错,调用方如何得知这个错误:

l  约定返回错误码

 

异常

java使用异常来表示错误:

l  异常是class,本身带有类型信息

l  异常可以在任何地方抛出

l  异常只需要在上层捕获,和方法调离

 

java的异常体系

java的异常本身就是class

l  Throwable

n  Error

n  Exception

u  RuntimeException

u  IOException

 

必须捕获的异常:

包括Exception及其子类,但不包括RuntimeException及其子类,称为Checked Exception

 

不需要捕获的异常:

l  error及其子类

l  RuntimeException及其子类

 

为什么java要定义这样异常体系?

error是发生了严重错误,程序对此一般无能为力

Exception是发生了运行时逻辑错误,应该捕获异常并处理

 

捕获异常

l  使用try…catch捕获异常

l  可能发生异常的语句放在try{}中

l  使用catch捕获对应的exception及其子类

 

可以使用多个catch子句:

l  每个catch捕获对应的Exception及其子类

l  从上到下匹配,匹配到某个catch后不再继续匹配

l  子类必须写在前面

 

finally

finally语句块保证有无错误都会执行

finally不是必须的

finally总是最后处理

multi-catch

如果某些异常的处理逻辑相同:

不存在继承关系,必须编写多条catch语句

可以使用|表示多种Exception

必须jdk>=1.7以上

 

 

 

申明异常

对可能抛出Checked Exception的方法调用

l  捕获Exception并处理

l  不捕获但通过throws声明

l  通过thorws声明仍需在上层捕获

l  main()是最后捕获Exception的机会

 

抛出异常

异常的传播

当某个方法抛出异常时:

l  如果当前方法没有捕获,异常就被抛到上层调用方法

l  直到遇到某个try…catch被捕获

l  printStackTrace()可以打印出方法的调用栈

 

抛出异常

如何抛出异常:

l  创建某个exception的实例

l  用throw语句抛出

 

转换异常

如果一个方法捕获了某个异常后,又在catch子句中抛出新的异常,就相当于把抛出异常类型转换了 :

新的异常丢失了原始的异常信息,所以要把原始的异常的实例e传进新的异常

 

抛出异常

如果在catch子句中又抛出一个异常,那么在抛出异常之前:

l  finally语句会保证执行

l  如果我们在finally语句中又抛出异常,那么原先catch的异常不再抛出

l  没有被抛出的异常称为被屏蔽的异常(suppressed exception)

 

java异常传播只能传播一个异常,后面抛出会把前面抛出且没有被catch覆盖

 

Suppressed

 

如何保存所有的异常信息?

l  用origin变量保存原始异常

l  如果存在原始异常,用addSuppressed()添加新的异常

l  如果存在原始异常,或新异常,最后在finally抛出

l  用getSuppressed()获取所有suppressed exception

l  jdk>=1.7

自定义异常

自定义异常应该从合适的exception派生

推荐RuntimeExcrption

自定义异常应该提供多个构造方法

 

断言和日志

Assertion

断言是一种程序调试方式

l  使用assert关键字

l  断言条件预期为 true

l  如果断言失败,抛出AssertionError

l  可选断言消息

 

assert x >= 0 : “x must >= 0”;

 

特点

l  断言失败时会抛出AssertionError,导致程序结束退出

l  不能用于可恢复的程序错误

l  只应该用于开发和测试阶段

 

什么是可恢复的错误:如果我们认为一个程序错误是可以恢复,例如:一个变量是否为空

对于可恢复的程序错误:

l  不应该使用断言

l  应该抛出异常在上层捕获

 

 

启用断言

jvm默认关闭断言指令

给java虚拟机传递-ea参数启用断言

可以指定特定的类启用断言: -ea:完整包名+类名

可以指定特定的包启用断言: -ea:完整包名…(注意最后加三个点)

 

断言很少被使用,更好的方法编写单元测试。

 

java日志

Logging

为了取代System.out.println()

可以设置输出样式

可以设置输出级别,禁止某些级别输出

可以被重定向到文件

可以按包名控制日志级别

 

 

JDK Logging

定义了7个日志级别:

SEVERE

WARNING

INFO

CONFIG

FINE

FINER

FINEST

 

局限

l  jvm启动时读取配置文件并完成初始化

l  jvm启动后无法修改配置

l  需要在jvm启动时传递参数

-Djava.util.logging.config.file = config-file-name

 

Commons Logging

是apache创建的日志模块

l  可以连接不同的日志系统

l  可以通过配置文件指定挂接的日志系统

l  自动搜索并使用Log4j

l  如果找不到Log4j,使用jdk Logging(jdk>=1.4)

 

定义了6个日志级别:

FATAL

ERROR

WARINNG

INFO

DEBUG

TRACE

 

使用Log4j

Log4j目前最流行的日志框架

l  1.x Log4j

l  2.x Log4j2

 

因为commons Logging 优先使用Log4j

建议始终使用commons Logging接口来写入日志

开发阶段无需引入Log4j

使用Log4j需要把正确的配置文件和相关的jar包放入classpath

使用配置文件可灵活修改日志,无修改代码

posted @ 2018-06-04 14:32  心悲动我神  阅读(284)  评论(0编辑  收藏  举报