11 异常、断言、日志和调试

对于异常情况,Java使用一种被称为异常处理的错误捕获机制处理。

11.1 处理错误

异常处理的任务就是把控制权从错误产生的地方转移到能够处理这种情况的错误处理器。

11.1.1 异常分类

所有异常都是从Throwable继承而来,接下来立即分为两支:Error和Exception。

Error类层次结构描述了Java运行时系统内部错误和资源耗尽错误。应用程序不应该抛出这种错误。

Exception类层次结构又分解为两个分支,一个分支派生于RuntimeException,另外一个分支包含其他异常。划分两个分支的规则是,由程序错误导致的异常属于RuntimeException;而程序本身没有问题,由于像I/O错误这种类型导致的异常属于其他异常。

“如果发生RuntimeException,那么一定是你的问题”。

派生于RuntimeException和Error类的所有异常称为未检查异常。所有其他异常称为已检查异常。编译器将核查是否为所有的已检查异常提供了异常处理器。

11.1.2 声明已检查异常

public FileInputStream(String name) throws FileNotFoundException

下面4种情况,应该抛出异常:

  1. 调用一个抛出已检查异常的方法,比如FileInputStream构造器。
  2. 程序运行当中发现错误。
  3. 程序出现错误,
  4. Java虚拟机和运行时库出现的内部错误。

总之,一个方法必须声明所有可能抛出的已检查异常。而未检查异常,要么不可控制,要么就应该避免发生。

除了声明异常之外,还可以捕获异常。这样会使异常不被抛到方法之外,也不需要throws规范。

抛出一个异常,而这个异常属于某个特定类的实例时,有可能抛出这个类,或者它的子类的异常。

11.1.3 如何抛出异常

找到一个合适的异常类;创造这个类的一个对象;将对象抛出。

11.1.4 创建异常类

遇到任何标准异常类都不能够充分描述清楚的情况,可以创建自己的异常类,需要定义一个派生于Exception类或者其子类的类。

习惯上,定义的类应该包括两个构造器,一个是默认的构造器,另外一个是带有详细描述信息的构造器。

11.2 捕获异常

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

通常,应该捕获那些知道如何处理的异常,而将那些不知道如何处理的异常继续传递。

11.2.1 捕获多个异常

11.2.2 再次抛出异常与异常链

在catch字句中可以抛出一个异常,这样做的目的是改变异常的类型。

11.2.3 finally子句

try/catch/finally。

无论在try语句块是否遇到异常,finally子句中的语句都会被执行。

事实上,我们认为需要关闭资源时,使用finally语句是个不错的选择。

11.2.4 带资源的try语句

假设资源属于一个实现AutoCloseable接口的类,Java se7为这种代码模式提供了一个很有用的快捷方式。

带资源的try语句(try-with-resource)的最简方式为:

try(Resoure res = ...) { work with res}

try块退出的时候,会自动调用res.close()。

11.2.5 分析堆栈跟踪元素

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

import java.util.*;


public class StackTraceTest
{
   
   public static int factorial(int n)
   {
      System.out.println("factorial(" + n + "):");
      Throwable t = new Throwable();
      StackTraceElement[] frames = t.getStackTrace();
      for (StackTraceElement f : frames)
         System.out.println(f);
      int r;
      if (n <= 1) r = 1;
      else r = n * factorial(n - 1);
      System.out.println("return " + r);
      return r;
   }

   public static void main(String[] args)
   {
      Scanner in = new Scanner(System.in);
      System.out.print("Enter n: ");
      int n = in.nextInt();
      factorial(n);
   }
}

11.3 使用异常机制的技巧

  1. 异常处理不能代替简单的测试
  2. 不要过分细化异常
  3. 利用异常层次结构
  4. 不要压制异常
  5. 苛刻比放任要好
  6. 不要羞于传递异常

11.4 使用断言

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

Java引入关键词 assert。

assert x >= 0;

11.4.1 启用和禁用断言

在默认情况下,断言被禁用。启用或者禁用断言是类加载器的功能。

11.4.2 使用断言完成参数检查

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

  • 日志
  • 断言
  • 异常

断言失败是致命的,不可恢复的错误;断言只适用于开发和测试阶段。

11.4.3 为文档假设使用断言

11.5 记录日志

记录日志,为了弥补println方法的缺点。

11.6 调试技巧

1,用println方法打印;

2,每个类中放置一个main方法,可以对每个类进行单元测试;

3,Junit;

4, 日志代理。

5,利用printStackTrace方法。

6,7,8,,,

11.7 GUI程序排错技巧

11.8 使用调试器

 

posted @ 2020-05-04 21:37  ayor  阅读(157)  评论(0)    收藏  举报