天天看点

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试

《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试

出现不可预计的问题时,需要进行如下处理:

  1. 报告错误
  2. 保存操作结果
  3. 允许用户退出

本章解决的问题:

  • 验证程序正确性
  • 记录程序错误
  • 调试技巧

11.1 处理异常

程序出现错误时应该:

  • 返回安全状态,能让用户执行其他命令
  • 允许用户保存所有操作结果,并能够终止程序

程序错误的关注点:

  1. 用户输入错误
  1. 不遵循程序要求,语法不正确,程序代码应该检查,如果没有检查,会出现错误(遇到过,没检查到,提示不友好用户投诉的)
  1. 设备错误
  1. 硬件不一定能够使用,比如打印机关上了,没纸了(这个处理好IO问题不大)
  1. 物理限制
  1. 磁盘满了(遇到过,数据库太大把磁盘占满,搬数据库)
  1. 代码错误
  1. 返回了错误的答案,或者错误的调用了其他方法(必然遇到过T T)

11.1.1 异常分类

Throwable下,分为Error和Exception

Exception下,又分爲IOException和RuntimeException

Error: Java运行时的内部错误和资源耗尽错误。这种错误通常是系统宕机级别的,处理起来时间较长。(比如没有磁盘空间了)通常在代码层面无法处理这种错误。

RuntimeException: 程序本身没有问题,IO错误等

常见的运行时异常:

  1. 数组越界
  2. 空指针
  3. 类型转换错误

检查异常:

  1. 错误URL
  2. 反射异常
  3. 读取超出文件尾部的数据

所以非运行时错误,一定是编码问题

11.1.2 声明已检查异常

无法处理的情况,Java方法可以抛出一个异常,告诉编译器要返回什么值,如果没有值,则返回发生的错误。

抛出异常的情况:

(1)调用抛出异常的方法

(2)运行过程中发生错误,抛出已检查异常

(3)程序错误,提供不应该提供的数值,a[-1]=0 会报越界异常

(4)Java 虚拟机和运行库异常

前两种必须捕获,不捕获可能宕机

抛出异常的方式:

Class MyAnimation{

Pubic Image loadImage(String s) throw EOFException,MalformedURLException{}

}

异常处理方式:

捕获:进行处理,展示给用户

抛出:交给上一层级处理

不处理:不可控的Error,或者使用规则限制,不产生额外的异常

特殊要求:

子类异常范围,不能超出父类异常范围

11.1.3 如何抛出异常

假设IO读取数据时不完整,可考虑抛出IOException, API 提议抛出 EOFException

基本格式:

public [返回值] 方法名(参数列表) 抛出列表{

        throw new XXException();

}      

11.1.4 创建异常类

有时候,标准异常描述并不能做到清楚具体,或者无法具体定位异常原因,为了进一步了解是程序中的哪一段出现异常,可考虑建立自己的异常类(个人觉得一个是名称识别,另外异常文字之类的可以做特殊处理,让它打印到log对应级别上而非直接输出)。

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

然后就可以像IOException一样使用这种异常

public class Main {
    public static void main(String[] args) throws FontFormatException {
        Main solution = new Main();

        solution.test(1);

    }

    private void test(int num) throws FontFormatException {
        if(num==1)
            throw new FontFormatException("test");
    }
}      

不传之密,异常处理工具,保留一定字数的异常信息(数据库存储大小是有限的):

public class ErrorUtil {
    public static String exceptionStr(Exception e, int length) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        e.printStackTrace(new PrintStream(baos));
        String exception = baos.toString();
        
        String regEx = "Caused by:(.*)";
        Pattern pat = Pattern.compile(regEx);
        Matcher mat = pat.matcher(exception);
        boolean rs = mat.find();
        if (rs) {
            if (mat.group(1).length() > length) {
                return mat.group(1).substring(0, length);
            } else {
                return mat.group(1);
            }
        } else {
            if (exception.length() > length) {
                return exception.substring(0, length);
            } else {
                return exception;
            }
        }
    }
    
    public static String exceptionStr(Exception e){
        return exceptionStr(e,800);
    }
    
    public static String getAllException(Exception e){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        e.printStackTrace(new PrintStream(baos));
        String exception = baos.toString();
        String regEx = "Caused by:(.*)";
        Pattern pat = Pattern.compile(regEx);
        Matcher mat = pat.matcher(exception);
        boolean rs = mat.find();
        if (rs) {
             return mat.group(1);
        } else {
             return exception;
        }
    }
}      

结合:

public class Main {
    public static void main(String[] args) {
        Main solution = new Main();

        try {
            solution.test(1);
        } catch (FontFormatException e) {
            System.out.println(ErrorUtil.getAllException(e));
        }

    }

    private void test(int num) throws FontFormatException {
        if(num==1)
            throw new FontFormatException("test");
    }
}      
《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试