Java-异常、断言和日志

处理错误

Java中,如果某个方法不能采用完整的途径完成它的任务,就可以通过另外一个路径退出方法。在这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。需要注意的是,这个方法将会立刻退出,并不返回任何值。此外,调用这个方法的代码也将无法继续执行,取而代之的是,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exception handler)。

异常分类

Java中,异常对象都是派生于Throwable类的一个实例。异常的层次结构如下所示

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

  • Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全地终止之外,再也无能为力了。这种情况很少出现。
  • 在设计Java程序时,需要关注Exception层次结构。这个层次结构又分为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RuntimeException;而程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常。
  • 派生于RuntimeException的异常包括:
    • 错误的类型转换
    • 数组访问越界
    • 访问null指针
  • 不是派生于RuntimeExcepiton的异常包括:
    • 试图在文件尾部后面读取数据
    • 试图打开一个不存在的文件
    • 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在

Java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查(unchecked)异常,所有其他的异常称为受查(checked)异常。编译器将核查是否为所有的受查异常提供了异常处理器。

: RuntimeException这个名字很容易让人混淆。实际上,现在讨论的所有错误都发生在运行时。

: 如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比超类方法中声明的异常更通用(也就是说,子类方法中可抛出更特定的异常,或者根本不抛出任何异常)。特别需要说明的是,如果超类方法没有抛出任何受查异常,子类也不能抛出任何受查异常。

捕获异常

编译器严格执行throws说明符。如果调用了一个抛出受查异常的方法,就必须对它进行处理,或者继续传递。通常,应该捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常继续进行传递。

如果想传递一个异常,就必须在方法的首部添加一个throws说明符,以便告知调用者这个方法可能会抛出异常。

finally子句

当代码抛出一个异常时,就会终止方法中剩余代码的处理,并退出这个方法的执行。如果方法获得了一些本地资源,并且只有方法自己知道,又如果这些资源在退出方法之前必须被回收,那么就会产生资源回收问题。这时一般使用finally子句。不管是否有异常被捕获,finally子句中的代码都被执行。

使用断言

在一个具有自我保护能力的程序中,断言很常用。

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

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

assert 条件;
以及 assert 条件:表达式;
复制代码

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

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

  • 抛出一个异常
  • 日志
  • 使用断言

什么时候应该选择使用断言呢?

  • 断言失败是致命的、不可恢复的错误
  • 断言检查只用于开发和测试阶段

断言是一种测试和调试阶段所使用的战术性工具;而日志记录是一种在程序的整个声明周期都可以使用的策略性工具。

### 记录日志

用来替代System.out.println方法,解决频繁插入删除System.out.println方法的问题。

log4j?

转载于:https://juejin.im/post/5b72ccbce51d4566252ab572

你可能感兴趣的:(Java-异常、断言和日志)