• 【Java技术路线】7. 异常与调试


    7 异常与调试

    7.1 内置异常

    在Java.lang中,Java定义了若干个异常类,这些异常一般是标准类RuntimeException的子类。因为java.lang实际上被所有的Java程序引入,多数从RuntimeException派生的异常都自动可用。Java语言中,这被叫做未经检查的异常(unchecked exceptions )。因为编译器不检查它来看一个方法是否处理或抛出了这些异常。
    未经检查的异常:
    ArithmeticException 算术错误,如被0除
    ArrayIndexOutOfBoundsException 数组下标出界
    ArrayStoreException 数组元素赋值类型不兼容
    ClassCastException 非法强制转换类型
    IllegalArgumentException 调用方法的参数非法
    IllegalStateException 环境或应用状态不正确
    IndexOutOfBoundsException 某些类型索引越界
    NullPointerException 非法使用空引用
    NumberFormatException 字符串到数字格式非法转换
    SecurityException 试图违反安全性
    StringIndexOutOfBounds 试图在字符串边界之外索引
    UnsupportedOperationException 遇到不支持的操作
    IllegalThreadStateException 请求操作与当前线程状态不兼容
    IllegalMonitorStateException 非法监控操作,如等待一个未锁定线程

    java.lang中定义的检查异常:
    ClassNotFoundException 找不到类
    CloneNotSupportedException 试图克隆一个不能实现Cloneable接口的对象
    IllegalAccessException 对一个类的访问被拒绝
    InstantiationException 试图创建一个抽象类或者抽象接口的对象
    InterruptedException 一个线程被另一个线程中断
    NoSuchFieldException 请求的字段不存在
    NoSuchMethodException 请求的方法不存在

    7.2 声明异常

    如果在项目当中遇到异常,不想通过try catch精准捕捉,那么可以通过throw 关键词抛出异常。
    例如:如果我们需要读取一份文件,但是有可能读取的文件不存在,或者内容为空,所以我们需要告诉编译器可能会出现FileNotFoundException类异常。

    public FileInputSteam(String name) throws FileNotFoundExceptionArrayIndexOutOfBoundsException // 可以抛出多个异常
    
    
    
    • 1
    • 2
    • 3

    在Java中,throw的使用格式如下:

    throw new 异常类名(参数);
    
    • 1

    例如:

    throw new NullPointerException("要访问的arr数组不存在");
    
    throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
    
    • 1
    • 2
    • 3

    声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

    关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
    声明异常格式:

    修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2{   }
    
    • 1
    public class ThrowsDemo {
        public static void main(String[] args) throws FileNotFoundException {
            read("a.txt");
        }
    
        // 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
        public static void read(String path) throws FileNotFoundException {
            if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
                // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
                throw new FileNotFoundException("文件不存在");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    7.3 自定义异常

    概述:如果遇到现有任何标准异常类都无法描述清楚的问题,这种情况下就需要创建一个属于自己的异常类了。
    如何:我们要做的就是定义一个派生于Exception 的类,或者子类,比如IOException。
    超类Throwable 的 toString 会返回字符串,很好用
    创建异常类应该包含两个构造器,一个是默认的构造器,一个是包含详细描述信息的构造器。

    /创建自定义异常类
    class FileFormatException extend IOException{
        public FileFormatException(){}  // 默认的构造器
        public FileFormatException(String gripe){  // 详细描述信息的构造器
            super(gripe);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // 抛出自定义异常类
    String readData(Buffered in) throws FileFormatException{
        ......
        while(...){
            if (. . .){
                throw new FileFormatException();
            }
          ......
        }
        return ...;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    7.4 捕获异常

    如果异常出现的话,会立刻终止程序,所以我们得处理异常:

    该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
    在方法中使用try-catch的语句块来处理异常。

    try-catch的方式就是捕获异常。

    捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
    捕获异常语法如下:

    try{
         编写可能会出现异常的代码
    }catch(异常类型  e){
         处理异常的代码
         //记录日志/打印异常信息/继续抛出异常
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    try:该代码块中编写可能产生异常的代码。

    catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

    注意:try和catch都不能单独使用,必须连用。
    示例代码:

    public class TryCatchDemo {
        public static void main(String[] args) {
            try {// 当产生异常时,必须有处理方式。要么捕获,要么声明。
                read("b.txt");
            } catch (FileNotFoundException e) {// 括号中需要定义什么呢?
              	//try中抛出的是什么异常,在括号中就定义什么异常类型
                System.out.println(e);
            }
            System.out.println("over");
        }
        /*
         *
         * 我们 当前的这个方法中 有异常  有编译期异常
         */
        public static void read(String path) throws FileNotFoundException {
            if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
                // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
                throw new FileNotFoundException("文件不存在");
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

    什么时候的代码必须最终执行?

    当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。

    finally的语法:

    try…catch…finally:自身需要处理异常,最终还得关闭资源。

    注意:finally不能单独使用。

    public class TryCatchDemo4 {
        public static void main(String[] args) {
            try {
                read("a.txt");
            } catch (FileNotFoundException e) {
                //抓取到的是编译期异常  抛出去的是运行期 
                throw new RuntimeException(e);
            } finally {
                System.out.println("不管程序怎样,这里都将会被执行。");
            }
            System.out.println("over");
        }
        /*
         *
         * 我们 当前的这个方法中 有异常  有编译期异常
         */
        public static void read(String path) throws FileNotFoundException {
            if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
                // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
                throw new FileNotFoundException("文件不存在");
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    多个异常使用捕获又该如何处理呢?

    多个异常分别处理。
    多个异常一次捕获,多次处理。
    多个异常一次捕获一次处理。
    一般我们是使用一次捕获多次处理方式,格式如下:

    try{
         编写可能会出现异常的代码
    }catch(异常类型A  e){try中出现A类型异常,就用该catch来捕获.
         处理异常的代码
         //记录日志/打印异常信息/继续抛出异常
    }catch(异常类型B  e){try中出现B类型异常,就用该catch来捕获.
         处理异常的代码
         //记录日志/打印异常信息/继续抛出异常
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

    7.5日志

    在Java程序中常用日志框架可以分为两类:

    无具体实现的抽象门面框架,如:Commons Logging、SLF4J

    具体实现的框架,如:Log4j,Log4j 2,Logback,Jul

    1.对于一个简单的应用,选择一个日志记录器,可以把日志记录器命名为与主应用包一样的名字,为了方便起见,可以为有大量日志记录活动的类增加静态字段。

    2.默认的日志配置会把级别等于或高于INFO的所有消息记录到后台,用户可以覆盖这个默认配置,但是改变配置的过程有些复杂。因此,最好在你的应用中安装一个更合适的默认配置。

    3.需要牢记:所有级别为INFO WARNING SEVERE的消息都将显示到控制台上。因此,最好只将对程序用户有意义的消息设置为这几个急别,将程序员想要的日志消息设定为FINE急别是一个很好的选择

  • 相关阅读:
    算法自学__线性筛
    单商户 V4.4,初心未变,实力依旧!
    JVM内存模型
    【Java篇】有关字节、字符流的知识你还记得吗?
    谷歌竞价排名,谷歌关键词优化,谷歌搜索引擎优化-大舍传媒
    树莓派入门
    《算法导论》第四版 电子版 全网第一时间发布eBookhub
    Spring的处理器映射器与适配器的架构设计
    ChaosBlade Java 场景性能优化,那些你不知道的事
    CentOS 7搭建LittlePaimon原神机器人
  • 原文地址:https://blog.csdn.net/sunnyblogs/article/details/127356550