(七)异常、断言、日志和调试

1. 错误来源:

  • 用户输入错误
  • 设备错误
  • 物理限制
  • 代码错误

2. 异常分类

  • 所有的异常都是继承Throwable,但是下一层立即分解为两个分支:Error和Exception
  • Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这种类型的错误。如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全的终止之外,再也无能为力
  • 需要关注的是Exception层次结构。这个结构又分为两个分支:由于程序错误导致的异常RuntimeException,还有程序本身没问题但由于I/O错误这类问题导致的异常IOException

3. RuntimeException:

  • 错误的类型转换
  • 数组访问越界
  • 访问空指针

4. IOException

  • 试图在文件尾部后面读取数据
  • 试图打开一个不存在的文件
  • 试图根据给定的字符串查找Class对象,而这个字符串表示的类不存在

5. 原则:

  • 如果出现RuntimeException异常,那么就一定是你的问题
  • 派生于Error类或RuntimeException类的异常称为未检查异常,所有其他异常称为已检查异常

6. 自己编写方法时,遇到下列几种情况应该抛出异常:

  • 调用一个抛出已检查异常的方法,例如FileInputStream构造器
  • 程序运行过程中发现错误,并且利用throw语句抛出一个已检查异常
  • 程序出现错误
  • Java虚拟机和运行时库出现的内部错误

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

8. 异常捕获或者 抛出:

  • 除了抛出异常之外,还可以捕获异常。
  • 应该捕获那些知道如何处理的异常,而将那些不知道怎么处理的异常继续进行传递。
  • 如果想传递一个异常就必须在方法的首部添加一个throw说明符,以便告知调用者这个方法可能会抛出异常
  • 仔细阅读API文档,以便知道每个方法可能抛出哪种异常,然后再决定是自己处理还是添加到throw列表中
  • 一旦方法抛出了异常,这个方法就不可能返回到调用者,也就是说不必为返回的默认值或错误代码担忧。

9. 如果在子类中覆盖了一个超类的方法,子类方法中声明的已检查异常不能比超类方法中声明的异常更加通用,也就是说,子类方法中可以抛出更特定的异常,或者根本不抛出任何异常。更甚,如果超类方法没有抛出任何已检查异常,子类也不能抛出任何异常。

10. 创建异常类,首先继承自某个异常类,然后自定义的异常类应该包含两个构造器,一个是默认的构造器,另一个是带有详细信息描述的构造器,调用super(message),打印出这些详细信息,这在调试中非常有用。

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

12. 在try{}cartch(Exception e){};代码段中,

  • try中任何代码抛出了一个在catch中说明的异常类,那么程序将跳过try代码块的其余代码,然后执行catch子句中的处理异常代码
  • try中任何代码抛出了一个在catch子句中没有声明的异常类型,那么这个方法就会立即退出 
  • 在一个try语句块中可以捕获多个异常类型,并对不同类型的异常做出不同的处理,try{}catch(Exception e1){}catch(FileNotFoundException e2){}catch(IOException e3){}..
  • 捕获多个异常不仅会让代码看起来简单还会更加高效,生成的字节码只包含一个对应公共catch子句的代码块
  • 要想获得异常的更多信息,可以使用e.getMessage()或者e.getClass().getName()得到异常对象的实际类型
  • 强力建议独立是哟个try/catch 和 try/finnaly 语句块,这样可以提高代码的清晰度
  • InputStream in = ...;
    try{
        try{
            code that might throw exceptions
        }finally{
            in.close();
        }
    }catch(IOException e){
        show error message;
    }

    内层的try语句块只有一个职责就是确保关闭输入流,外层的try语句块也只有一个功能,就是确保报告出现的错误,这种设计不仅清楚,而且还具有一个功能就是将会报告finally子句中出现的错误

  • final代买块的好处是一定会执行,对于那些需要释放资源的地方尤其重要

13. 使用异常的技巧:

  • 异常处理不能代替简单的测试,与执行简单的测试相比,捕获异常所花费的时间大大超过了前者,因此使用异常基本规则是,只在异常情况下使用异常机制
  • 不要过分的细化异常:最好的方式是将整个任务包装在一个try语句块中,这样当任何一个操作出现问题时,整个任务都可以取消
  • 利用层次异常结构,不要只抛出RuntimeException异常,应该寻找更加适当的子类或者创建自己的异常类
  • 不要压制异常,什么都不处理在异常语句中
  • 在检测错误时,苛刻要比放任更好
  • 不要羞于传递与异常,早抛出,晚捕获。

14. Java中三种处理系统错误的机制:

  • 抛出一个异常
  • 日志:为了解决在使用system.out.println()函数不断的更改删除的不便
  • 使用断言

 

posted @ 2016-03-27 20:18  桃源仙居  阅读(309)  评论(0)    收藏  举报