第七章 异常, 断言和日志

处理错误

  • 出现错误时程序应该(1)返回安全状态并允许用户执行一些其他命令; (2)或者允许用户保存所有操作的结果,并以妥善方式退出程序;
  • 错误产生的原因:(1)用户输入错误;(2)设备错误;(3)物理限制;(4)代码错误: 有些情况下代码的调用方并不能根据程序的错误返回码进行处理, 这时就需要抛出异常给异常处理器去处理;
  • 应用程序不应该抛出Error级别的错误, 出现这种错误一般时JVM或者资源耗尽, 除了通知用户并中止程序外,无法再做更多;
  • Exception 的子类 RuntimeException 表示异常时由程序错误导致, 如果出现RuntimeException异常, 程序员就一定有责任去处理杜绝它.
  • 派生于ErrorRuntimeException的异常被称为unchecked异常, 其他为checked异常. (checked翻译为受查)
  • 下面四种情况下应该抛出异常: 1. 调用了抛出异常的方法; 2. 程序throw出一个异常; 3. 程序出错; 4. JVM或运行时库报错
  • 对于给外部调用的方法, 有义务在方法上声明throws异常(checked)类型, 但不包括Error(调用方没能力处理)还有RuntimeException非受查异常(程序员有义务避免)

捕获异常

  • Java7 允许一个catch中捕获多个类型异常, 变量e隐含final修饰的 catch(FileNotFoundException | UnknownHostException e) { . . . }
  • 最佳实践: 重新包装的异常使用 Throwable.initCause(e) 可以设置异常的原因
  • 强烈建议解耦合使用try/catch和try/finally
try
{
    try
    {
        code that might throw exceptions
    }
    finally
    {
        in.close() ;
    }
    }
    catch (IOException e)
    {
        show error message
    }
}
  • 接口 AutoCloseable ,Closeable(继承自AutoCloseable) , 实现类的方法可以使用try(😉{}块实现资源自动回收.即相当于finally中调用接口的close()方法. 如果close()方法中也抛出异常, 会被增加到原有异常中, 而finally{}则会替换原有异常.

异常处理的技巧

  1. 异常处理代替不了单元测试
  2. 不要过分细化异常, 如每行代码分别捕获
  3. 利用异常层次结构, 如使用更准确的子类,不要都抛出Exception类
  4. 不要压制异常, 如catch{}空处理罕见不重要的异常
  5. 检查错误时, 苛刻比放任更好, 在早期抛出异常更合适 早抛出
  6. 不要羞于传递异常 晚捕获

使用断言

  • 断言默认不启用,通过java -ea AppName启用, 其时类加载器的功能,不启用则跳过; -ea, -da, -esa分别时启用,禁用,启用系统类断言
  • Java中三种处理系统错误的方式1. 抛出异常; 2. 日志 ; 3. 使用断言
  • 断言的特征: 1. 断言失败是致命的, 不可恢复的错误; 2.断言检查只用于开发,测试阶段;
  • 断言是测试和调试阶段的战术性工具

调试技巧(只列出不常用但可能有用的)

  • java -verbose 标志启动JVM可以查看类加载情况
  • javac -Xlint <> 可以对一些常见问题进行检查
  • jmap工具可以获取一个堆的转储 jmap -dump:format=b,file=dumpFileName processsID Jhat dumpFileName
  • java -Xprof 标记可以跟踪那些代码常被调用的方法并输出到控制台
posted @ 2018-09-10 19:39  罪恶斯巴克  阅读(265)  评论(0编辑  收藏  举报