java核心技术日志记录_Java核心技术 卷1 基础知识—异常、断言和日志

《第7章 异常、断言和日志》

异常

1.异常分类

在Java中,异常对象都是派生于Throwable类的一个实例。

如果Java内置的异常类不能够满足需求,用户可以创建自己的异常类

6e0c7b5bf99d582c4bb569232cffaa95.png

需要注意的是所有异常都是由Throwable继承而来,但在下一层立即分解为两个分支

Error和Exception

Error类层次结构描述了Java运行时系统的内部错误和自愿耗尽错误,应用程序不应该抛出这种类型的对象。

在Java程序设计时,需要关注Exception层次结构

Exception层次结构又分解为两个分支:

一个分支派生于RuntimeException

另一个分支包含其他异常

划分这两个分支的规则为:

由程序错误导致的异常属于RuntimeException

程序本身没有问题,但由于像I/O错误这类问题导致的属于其它异常

一般来说,属于RuntimeException的有:

错误的类型转换

数组访问越界

访问null指针

属于其它异常的有:

试图在文件尾部后面读取数据

试图打开一个不存在的文件

试图根据给定的字符串查找class对象,而这个字符串表示的类并不存在

Java将派生于Error类或RuntimeException类的所有异常称为非受查异常

所有其他的异常称为受查异常

而编译器将核查是否为所有的受查异常提供了异常处理器

2.声明受查异常

如果遇到了无法处理的情况,那么Java的方法可以抛出一个异常

方法应该在其首部声明所有可能抛出的受查异常

不需要声明可能抛出的非受查异常

因为非受查异常要么不可控制(Error),要么应该避免发生(RuntimeException)

例如,我们读取文件常用到的类FileInputStream的read函数

其read构造函数的定义如下:

public int read() throws IOException {

return read0();

}

这个read函数的声明表示如执行成功将返回int类型的数据

但也有可能抛出一个IOException异常

同时由于该异常为受查异常,所以必须为其提供异常处理器

怎么调用一个可能会抛出受查异常的方法呢?

调用的方式一般有两种:以FileInputStream打开文件为例

一种是在方法中直接使用throws语句来继续传递异常

public void readFile() throws FileNotFoundException{

FileInputStream fileInputStream = new FileInputStream("hello.txt");

...

}

特别需要说明的是,如果在子类中覆盖了超类的一个方法

如果超类方法没有抛出任何受查常

子类也不能抛出任何受查异常

另一种则是使用try-catch语句将其捕获并处理

try {

FileInputStream fileInputStream = new FileInputStream("hello.txt");

...

}

catch (FileNotFoundException e){...}

3.如何抛出异常

一个简单的例子:一个名为readData的方法读取一个文件

当读取的字符数(n)小于文件的总字符数(len)时抛出异常

String readData(Scanner in) throws EOFException{

...

while(...){

if(!in.hasNext()){

if(n

}

...

}

}

其中EOFException是已经存在的异常类型,若是我们想要抛出属于我们自己的异常类型

可以新建一个类继承于Exception类然后再使用throw关键词抛出即可

4.捕获异常

要想捕获一个异常,必须设置try/catch语句

一般的try/catch语句如下:

try {

...

}

catch (ExceptionType e){

...

}

这里需要注意的是:

如果方法中的任何代码抛出了一个在catch子句中没有声明的异常类型

那么这个方法将立即退出

在try语句块中可以捕获多个异常类型

并对不同的异常类型做出不同的处理

try{

...

}

catch(FileNotFoundException e){...}

catcg(UnkownHostException e){...}

catch(IOException e){...}

可以使用e.getMessage()得到更为详细的信息

可以使用e.getClass().getName()得到异常对象的实际类型

当然,我们也可以选在在catch语句中再次抛出异常

这样做的目的一般是为了改变异常的类型

try/catch语句一般也搭配finally使用

不管有无异常被捕获,finally子句的代码都会被执行

5.使用异常机制的技巧:

异常处理不能代替简单的测试

不要过分地细化异常;如不要将一条语句封装在一个独立的try语句中

利用异常层次;

不要压制异常;

在检查错误时,“苛刻”要比放任好

不要羞于传递异常

断言

断言机制允许在测试期间想代码插入一些检查语句。当代码发布时,这些插入的测试语句将被自动地移走

Java引入了关键字assert,对应的有两种形式

assert 条件;

assert 条件:表达式;

这两种形式都会对条件进行检测,若结果为false,则抛出一个AssertError异常。

在第二种形式中,表达式将会被传入AssertError的构造器,并转换成一个消息字符串

在默认情况下,断言被禁用,需要开启。

什么时候使用断言呢?

断言失败是致命的,不可恢复的错误

断言检查只用于开发和测试阶段。断言只应该用于在测试阶段确定程序内部的错误。

记录日志

每个Java程序员都很熟悉在有问题的代码中插入System.out.println方法调用来帮助观察程序运行的过程,

而一旦发现问题的根源,就要将这个打印语句删除。若其他地方还有问题,则需要重复这种写打印语句又删除的行为。

而记录日志则提供了一种更为科学的方法。

要生成简单的日志记录,可以使用全局日志记录器并调用其info方法:

Logger.getGlobal().info("File->Open menu item seleceted");

Logger.getGlobal().info("x"+x);//输出某个变量的值

但是在适当的地方(如main开始)调用

Logger.getGlobal.setLevel(Level.OFF);

就会取消所有的日志。

在一个专业的应用程序中,不要将所有的日志都记录到一个全局日志记录器中,而是可以自定义日志记录器

可以调用getLogger方法来创建或者获取记录器

private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp");

用一个静态变量存储日志记录器的引用

记录日志的常见用途是记录那些不可预料的异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值