CoreJava 笔记总结-第七章 异常,断言和日志

第七章 异常,断言和日志

处理错误

异常的分类

  • 异常对象都是派生于Throwable类的一个类实例
  • 下一层:Error:描述java运行时系统内部错误或者资源耗尽错误 Exception: 其他异常(IOException), RuntimeException(编程错误导致的异常)
  • RuntimeException: 错误的强制类型转换,数组访问越界,访问null指针
  • 非检查型异常: Error, RuntimeException, 其他的异常称为检查型异常

声明检查型异常

  • 一个方法必须声明所有可能抛出的检查型异常,而非检查型异常:Error在控制之外, RuntimeException一开始就应该避免的情况
  • 子类中覆盖了超类的一个方法,子类中声明的检查型异常必须特殊性大于等于超类中的(不抛出或者抛出更加特殊的异常)

如何抛出异常

  • 方法: 找到一个合适的异常类–>创建这个类的一个对象–>将对象抛出

  • throw new EDFException

  • var e = new EDFException();
    throw e;
    
  • throw new EOFException(string)


创建异常类

  • 定义一个派生于Exception的类或者其子类,包含两个构造器:默认构造器和一个包含详细描述信息的构造器

  • class FileFormatException extends IOException
    {
        public FileFormatException(){}
        public FileFormatException(Strig gripe){super(gripe);}
    }
    

捕获异常

捕获单个异常

  • try{
        code
        more code
    }
    catch(ExceptionType e){
        handle for this type
    }
    
  • 捕获知道怎么处理的异常, 传播不知道如何处理的异常

  • public void read(String filename){
        try{
            var in = new FileInputStream(filename);
            int b;
            while((b = in.read())!= -1){...}
        }
        catch(IOException exception){
            exception.printStackTrace();
        }
    }
    
    public void read(String filename) throws IOException
    {
        var in = new FileInputStream(filename);
        int b;
        while((b = in.read())!= -1){...}
    }
    
  • 子类方法覆盖超类,超类没有抛出异常,子类必须捕获


捕获多个异常

  • try{
        code
        more code
    }
    catch(FileNotFoundException e){
        emergency action for missing files
    }
    catch(UnknowHostException e){
        emergency action for unknow hosts
    }
    catch(IOException | ExceotionType e){
        emergency action for all i/o problems
    }
    
  • e.getMessage()获取错误信息

  • e.getClass().getName()获得异常对象实际类型


再次抛出异常和异常链

  • 将原始异常设置为新异常的原因
  • 子系统中抛出高层异常,而不会丢失原始异常的细节
  • 可以将检查型异常包装为非检查型异常

finally子句

  • try{
        ..
    }
    catch{
        ...
    }
    finally{
        ...
    }
    
  • finally子句中的代码一定会执行,可以没有catch子句

  • 不要把改变控制流的语句return , throw, continue, break放在finally子句中


try-with-Resource语句

  • try(Resource res= . . .){
        work with res
    }
    

    try块自动退出时,自动调用res,close()


分析堆栈轨迹元素

  • package chapter7_exception_assertion_logger.stackTrace;
    
    import java.util.Scanner;
    
    public class StackTraceTest {
    	//阶乘
        public static int factorial(int n) {
            System.out.println("factorial(" + n + "):");
            var walker = StackWalker.getInstance();
            walker.forEach(System.out::println);
            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) {
            try (var in = new Scanner(System.in)){
                System.out.println("Enter n: ");
                int n = in.nextInt();
                factorial(n);
            }
        }
    }
    

使用异常的技巧

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

使用断言

  • 断言:允许在测试期间在代码中插入一些检查,而在生产代码中会自动删除这些检查
  • assert condition;
  • assert condition: expression;

使用断言完成参数检查

  • 断言使用规则: 断言失败是致命的,不可恢复的错误; 断言只是在开法和测试阶段打开

  • assert a!= null;
    
  • 3种处理系统错误的机制: 抛出异常,断言,日志


日志

基本日志

  • 生成简单的日志,使用全局日志记录器Logger.getGlobal().info("File->Open menu item selected");

    9月 05, 2021 11:24:59 上午 chapter7_exception_assertion_logger.test.log main 信息: File->Open menu item selected.

  • Logger.getGlobal().setLevel(Level.OFF)将会取消所有的日志


高级日志

  • P306

调试技巧

  1. System.out.println("x=" + x); ``Logger.getGlobal().info("x=" + x);``Logger.getGlobal().info("this=" + this);打印或者记录任意变量的值
  2. 每一个类中单独放置main方法
  3. 日志代理:一个子类对象,截获方法调用,记录日志,调用超类中的方法.
var generator = new Random(){
    public double nextDouble(){
        double result = super.nextDouble();
        Logger.getGlobal().info("nextDouble: " + result);
        return result;
    }
};

System.out.println(generator.nextDouble());
/*
9月 05, 2021 11:48:19 上午 chapter7_exception_assertion_logger.test.log$1 nextDouble
信息: nextDouble: 0.8803807382089267
0.8803807382089267
*/
  1. 利用Throwable类的printStackTrace方法,可以从任意异常对象获得堆栈轨迹
try{
    ...
}
catch(Throwable t){
    t.printStackTrace();
    throw t;
}

或者:
Thread.dumpStack();
  1. 堆栈轨迹一般显示在System.err上.想要记录或者显示堆栈轨迹,可以捕获进入一个字符串

    import java.io.*;

var out = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(out));
String description = out.toString();
//System.out.println(description);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风起风里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值