Java基础学习(七)

Java基础学习(七):异常机制

本文为个人学习记录,内容学习自 狂神说Java黑马程序员


概念

异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等

异常发生在程序运行期间,它影响了正常的程序执行流程


简单分类

异常 vs 错误

  • 异常(Exception)

    • 异常是开发者可以在程序中进行处理的(可以通过编写异常处理语句,在出现异常时进行处理以恢复程序的正常运行)

    • 检查性异常:在编译时由编译器强制检查的异常,开发者必须处理这些异常才能编译通过

    • 运行时异常:在编译时可以被忽略的异常,程序运行时才会出现

  • 错误(Error)

    • 错误是开发者无法在程序中进行处理的(错误发生时就无力回天了,只能避免错误的发生)
    • 当出现错误时,JVM 一般会直接终止线程

异常体系结构

  • Java 把异常当作对象来处理,并定义了一个基类 Java.lang.Throwable 作为所有异常的超类(即最顶层的类)

  • 在 Java API 中已经定义了许多异常类,这些异常类分成两大类 —— 错误和异常

  • 下图给出了一些常见错误Error和异常Exception,仅表示大体结构,例如 RuntimeException 和 ArrayIndexOutOfBoundsException 中间还省略了一些子/父类

  • RuntimeException 本身和其所有子类构成了运行时异常,其余所有异常均为编译时异常

    图7-1

异常处理机制

  • 抛出异常

    int a = 1;
    int b = 0;
    System.out.println(a/b);							// 由于0不能作为除数,程序会抛出异常
    =========================================================================================================
    输出结果:
    Exception in thread "main" java.lang.ArithmeticException: / by zero
    
  • 捕获异常

    可以通过 try-catch 语句捕获异常,从而使程序在有异常的情况下继续执行

    int a = 1;
    int b = 0;
    try {
        System.out.println(a/b);						// 将可能抛出异常的语句放入try修饰的代码块中
    }catch (ArithmeticException e){						// 指明想捕获的异常类型
        System.out.println("程序出现异常才会执行");		// 如果捕获到了指定异常会执行的语句,通常是处理语句
    }finally {											// finally代码块是可选项,无论是否捕获到异常都会执行
        System.out.println("无论如何都会执行");
    }
    System.out.println("继续执行");						// 就算存在异常,程序也会继续执行下去
    

    几点补充:

    1. 想捕获的异常类型也可以是具体异常类的父类,例如写 catch (Throwable e) 时能够捕获到其下所有的错误和异常

    2. catch 语句可以存在多个,类似于 else if 语句,从上往下执行当捕获到异常后就不会执行剩余的 catch 语句了

    3. 如果在 try 语句块内没有捕获到异常,那么 try 语句块中内容能正常执行,而 catch 语句块中的内容不会被执行

    4. 如果在 try 语句块内捕获到了指定异常,那么 try 语句块中异常之前的内容能正常执行,异常之后的内容不会再被执行

    5. finally 语句块内的内容一定会执行,不管是不存在异常/存在异常且成功捕获/存在异常但未成功捕获,都会执行;如果 try 语句块中有 return,那么 finally 语句块会在 try 的 return 之前执行,所以此时若 finally 语句块中也有 return,那么后者会覆盖前者。但需要注意,try 中 return 的返回值在执行 finally 语句块前就确定了,只是先跳转到 finally 中执行完后再返回而已

    6. JDK7 新增功能:如果存在多个 catch 语句块,且这些语句块的执行内容相同,那么可以在 catch 中同时捕获多个异常,例如:

      catch (ArrayIndexOutOfBoundsException | ArithmeticException e) {}
      
  • 主动抛出异常

    注意:主动抛出异常后,剩余代码将不会继续执行,除非使用 try-catch 语句捕获异常(和程序自动抛出的异常同理)

    • 方法内抛出异常(使用 throw 关键字)

      throw new ArithmeticException();				// 主动抛出一个算术异常
      
    • 方法上抛出异常(使用 throws 关键字)

      • 写在方法定义处,用于告诉调用者本方法可能会有哪些异常,多个异常之间用逗号隔开
      • 如果是编译时异常则必须要写,运行时异常可以省略不写
      public static void main(String[] args) {
          int a = 1;
          int b = 0;
          try {
              test(a, b);
          } catch (ArithmeticException e) {
              System.out.println("");
          }
      }
      public static void test(int a, int b) throws ArithmeticException{		// 使用throws关键字指定异常类型
          System.out.println(a/b);
      }
      

异常中的常见方法

Throwable 的成员方法:

方法名 说明
public String getMessage() 返回此异常的消息
public String toString() 返回此异常的描述
public void printStackTrace() 把异常的错误信息输出在控制台

示例:

int[] arr = {1, 2, 3};
try {
    System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException e) {
    String str1 = e.getMessage();
    String str2 = e.toString();
    e.printStackTrace();
}

自定义异常

  • 使用 Java 内置的异常类可以描述编程时出现的大部分异常情况

  • 自定义异常的作用:让控制台的报错信息更加直观

  • 自定义异常类的步骤:

    1. 定义异常类:起名需要见名知意

    2. 写继承关系:如果是编译时异常则继承 Exception 类,如果是运行时异常则继承 RuntimeException 类

    3. 构造函数:直接使用 alt+Insert 生成空参构造和形参为字符串的带参构造

    4. 示例:一个起名格式的自定义异常

      public class NameFormatException extends RuntimeException {
          // 空参构造
          public NameFormatException() {
          }
      
          // 带参构造
          // 抛出异常时,可以通过throw new NameFormatException("名字格式有误")创建异常对象
          // 这样在调用e.printStackTrace()时就可以输出自定义的异常信息
          public NameFormatException(String message) {
              super(message);
          }
      }
      
posted @   victoria6013  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示