写点什么

2020 年 6 月 10 日 异常、断言和日志

发布于: 2020 年 06 月 10 日

本章节主要是对于Java程序中处理错误、使用断言、捕获异常、记录日志、使用异常机制的技巧,调试技巧等进行说明

1、处理错误

常见的错误关注点:用户输入错误、设备错误、物理限制、代码错误

1、异常分类

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

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

Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。

在设计Java程序时,需要关注Exception层次结构。这个层次结构有分解为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。

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

常见的派生与RuntimeException的异常包含以下几种情况:

  • 错误的类型转换

  • 数组访问越界

  • 访问null指针

不是派生于RuntimeException有:

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

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

  • 试图根据指定的字符串查找Class对象,而这个字符串表示的类不存在

2、声明受检查异常

一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误。方法应该在其首部声明所有可能抛出的异常。

常见的四种抛出异常的情况;

  • 调用一个抛出受查异常的方法

  • 程序运行过程中发现错误,并且利用throws语句抛出一个受查异常

  • 程序出现错误

  • java虚拟机和运行时库出现的内部错误

3、如何抛出异常

对于一个已经存在的异常类,将其抛出非常的容器。在这种情况下:

  • 找到一个合适的异常类

  • 创建这个类的一个对象

  • 将对象抛出

一旦抛出了异常,这个方法就不可能返回到调用者。也就是说,不必为返回的默认值或错误代码担忧。

4、创建异常类

创建一个异常类,我们需要做的只是定义一个派生于Exception的类,或者派生于Exception子类的类。

例如,定义一个派生于IOException的类,习惯上,定义的类应该包含两个构造器,一个是默认构造器,另一个是带有详细描述信息的构造器

2、捕获异常

1、捕获异常

如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止运行,并在控制台上打印出异常信息。其中包括异常的类型和堆栈内容。

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

如果在try语句中的任何一个代码位置抛出了一个在catch子句中说明的异常类,那么

1)程序将跳过try语句块的其余代码

2)程序将执行catch子句中的处理器代码

如果方法中的任何代码抛出了一个在catch子句中没有声明的异常类型,那么这个方法就会立即退出

2、捕获多个异常

在一个try语句块中可以捕获多个异常类型,并对不同类型的异常做出不同的处理,可以按照下列方式为每个异常类型使用一个单独的catch子句:

try{
dosomething;
}catch( FileNotFoundException e){
e.printStackTrace();
}catch(UnknownEcxeption e){
e.printStackTrace();
}

3、再次抛出异常与异常链

在catch子句中可以抛出一个异常,这样做的目的是改变异常类型。如果开发了一个供其他程序员使用的子系统,那么用于表示子系统故障的异常类型可能会产生多种解释。就需要通过改变异常类型来给出明确地指示。

4、finally子句

不管异常是否被捕获,finally子句中的代码都会被执行

5、带资源的try语句

带资源的try语句的最简形式为:

try(Resource res = ...){

work with res...

}

这个块退出时,会自动调用res.close().

6、分析堆栈轨迹元素

堆栈轨迹是一个方法调用过程的列表,它包含了程序执行过中方法调用的特定位置。

StackTraceElement类含有能够获得文件名和当前执行的代码行号的方法,同时还有能够获得类名和方法名的方法。

静态的Thread.getAllStackTrace方法,它可以产生所有线程的堆栈轨迹

3、使用异常机制技巧

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

2、不要过分的细化异常

3、利用异常层次结构,不要只抛出RuntimeException。应该寻找更合适的子类,或创建自己的异常类

4、不要压制异常

5、在检查错误时,“苛责”要比放任更好

6、传递异常要比捕获异常更好

4、使用断言

1、断言的概念

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

Java引入了关键字assert。这个关键字有两种形式:

1、assert 条件;2、 assert 条件:表达式;

这两种形式都会对条件进行检测,如果结果为false,则抛出一个AssertionError异常。在第二种形式中,表达式将被传入AssertError的构造器中。

2、启用和禁用断言

默认情况下,断言被禁用,可以用运行程序时用 -enableassertions或-ea选项启用:

java -enableassertions MyApp

需要注意的是,在启用或禁用断言时,不必重新编译程序。启动或禁用断言时类加载器的功能。

3、使用断言完成参数检查

在Java语言中给出了3种处理系统错误的机智:

1、抛出一个异常

2、日志

3、使用断言

什么时候使用断言呢?请记住一下几点;

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

2、断言检查只用于开发和测试阶段

5、记录日志

1、基本日志

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

Logger.getGlobal().info("loger");

但是如果在适当的地方调用

Logger.getGlobal().setLevel(Level.OFF);

2、高级日志

可以调用getLogegr方法创建或获取记录器:

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

通常日志有七个纪录级别:

  • SEVER

  • WARNING

  • INFO

  • FINE

  • FINER

  • FINEST

在默认的情况下,只记录前三个级别。默认的日志记录将包含日志调用的类名和方法名。

3、修改日志管理配置

在默认情况下,配置文件存在于:jre/lib/logging.properties

要想使用另一个文件,就要将java.util.logging.comfig.file特性设置为配置文件的存储位置,并用下面的命令启动应用程序:

java -Djava.util.logging.config.file = configFile MainClass

4、处理器

在默认的情况下,日志记录器将记录发送到ConsoleHandler中,并由它输出到System.err流中。特别的是日志记录器还会将记录发送到父处理器中,而最终的处理器有一个ConsoleHandler

5、过滤器

在默认情况下,过滤器根据日志记录的级别进行过滤。每个日志级别记录器和处理器都可以有一个可选的过滤器来完成附加的过滤器。另外还可以实现Filter接口并定义isLoggable(LogRecord record)来自定义过滤器。

6、格式化器

ConsoleHandler类和FileHandler类可以生成文本和XML格式的日志记录。但是也可以自定义格式。这需要扩展Formatter类并覆盖下面这个方法:

String format(LogRecord record);

6、调试技巧

1、可以用System.out.println()方法打印或记录任意变量的值

2、在每一个类中放置一个单独的main方法这样就可以对每一个类进行单元测试

3、可以使用junit包进行单元测试

4、日志代理是一个子类的对象,它可以截获方法调用,并进行日志记录,然后调用超类中的方法。

5、打印异常和堆栈轨迹,然后重新抛出异常

6、将一个程序中的错误信息保存到文件中

7、java虚拟机增加了对java应用程序进行监控和管理的支持。

用户头像

还未添加个人签名 2020.05.18 加入

还未添加个人简介

评论

发布
暂无评论
2020年6月10日        异常、断言和日志