处理错误
由于出现错误而使得某些操作没有完成,程序应该
- 返回一种安全装填,能让用户执行其他命令
- 允许用户保存所有工作结果,以妥善的方式终止程序
异常处理机制能处理异常状况的异常处理器,异常有自己语法和特定继承层次结构
异常分类
所有异常都是由Throwable继承的,下一层立即分解为两个分支:Error和Exception
由编程错误导致的异常属于RuntimeException,如果程序自身没有问题,由于像I/O错误这类问题导致的异常属于其他异常
派生于RuntimeException的异常包括:
- 错误的强制类型转换
- 数组访问越界
- 访问null指针
不派生于RuntimeException的异常
- 试图超越文件末尾继续读取数据
- 试图打开一个不存在的文件
- 试图根据给定的字符串查找Class对象,而这个字符串表示的类不存在
java语言规范将派生于Error类或RuntimeException类的所有异常称为非检查型异常,其他异常叫检查型异常
声明检查型异常
遇到无法处理的情况,java方法可以抛出一个异常
试图处理文件信息的代码需要通知编译器可能会抛出IOException类的异常
什么时候需要在方法中用throws子句声明异常,以及用throws子句声明那些异常,有下面4种情况
调用一个抛出检查型异常的方法
检测到一个错误,用throw子句声明
程序出现错误
java虚拟机或运行时库出现内部错误
一个方法必须声明所有可能抛出的检查型一场,非检查型异常子啊控制之外(Error),最好一开始避免。
不只是声明异常,还可以捕获异常try catch,不会从这个方法抛出异常,没必要throws
怎么抛异常
一个已经有的异常类能满足要求,抛出这个异常非常容易:
- 找到一个合适的异常类
- 创建这个类的一个对象
- 将对象抛出
一旦抛出,这个方法就不会返回调用者,不必操心建立默认返回值或错误码
创建异常类
定义一个派生于Exception的类,或派生与Exception的某个子类
自定义这个类包含两个构造器,默认和包含详细信息的
捕获异常
捕获异常
发生异常没有捕获,程序就会终止,在控制台打印一个消息
一般经验,要捕获你知道如何处理的异常,继续传播你不知道怎样处理的异常
将异常交给胜任的处理器比压制这个异常更好,
例外:超类没异常,子类异常,必须捕获
捕获多个异常
在一个语句块中可以捕获多个异常类型,对不同类型异常做出不同的处理,要为每个异常类型使用一个单独的catch子句
再次抛出异常和异常链
可以在catch子句中在抛出一个异常,这是希望改变异常的类型
finally子句
代码抛出异常,会停止处理方法中剩余的代码,退出方法
不管异常是否被捕获,finally子句代码都会执行
执行finally三种情况:
- 代码没有抛出异常
- 代码抛出一个异常
- 代码抛出一个异常,没有catch捕获他
try分内外两层,内层关闭流,外层报告错误
try-with-Resources 语句
oper a resource
try
{
work with the resource
}
finally
{
close the reource
}
分析堆栈轨迹元素
堆栈轨迹是程序执行过程中某个特定点所有挂起的方法调用的一个列表
使用异常技巧
- 异常处理不能代替简单的测试,耗时长,只在异常情况下使用异常
- 不要过分的细化异常,try中应该含多个语句
- 充分利用异常层次结构,不要只抛出异常,要找适合的子类和创建自己的异常类,不要捕获,会让代码难懂
- 不要压制异常,catch中要有代码
- 在检测错误是,苛刻比放任好
- 不要羞于传递异常
- 早抛出,晚捕获
使用断言
断言概念
在程序中含有检查型代码,程序会跑的慢很多
断言允许在测试时在代码中插入一些检查,在生产代码中自动删除这些检查
assert condition :
assert condition : expression
启用和禁用断言
默认断言禁用的
不必重新编译程序来启用或禁用断言,这是类加载器的功能,禁用断言,类加载器会去除断言代码
使用断言进行参数检查
java语言中有三种处理错误机制:
- 抛出一个异常
- 日志
- 使用断言
使用断言的时机:
- 断言失败是致命的,不可恢复的错误
- 断言检查只是在开发和测试
不应该使用断言向程序其他部分通知发生了可恢复性的错误
不应该用断言与程序用户沟通问题
断言只应该用于在测试阶段确认程序内部错误位置
使用断言提供假设文档
if(i % 3 == 0)
...
else if(i % 3 == 1)
...
else //(i % 3 == 2)
断言
if(i % 3 == 0)
System.out.println(i);
else if(i % 3 == 1)
System.out.println(i++);
else //(i % 3 == 2)
{
assert i % 3 == 2;
System.out.println("ddd");
}
程序员应该如何使用断言来进行自我检查,断言是一种测试和调试阶段使用的战术性工具,日志是一种在程序整个生命周期都可以使用的工具
日志
基本日志
生成简单的日志,可以使用全局日志记录器
Logger.getGlobal().info("File -> Open menu item selected");
一月 18, 2022 10:59:42 上午 com.fu.javatec.chapter06.Demo07 main
信息: File -> Open menu item selected
取消日志
Logger.getGlobal().setLevel(Level.OFF);
高级日志
日志记录器
private static final Logger myLogger = Logger.getLogger("com.fu.javatec.chpter06");
修改日志管理器配置
编辑配置文件
conf/logging.properties
日志技巧
- 对一个简单应用,选择日志记录器
- 默认日志配置会把级别等于或高于INFO的所有消息记录到控制台
- 记录自己想要的内容