Exception与Error
Java程序在执行过程中所发生的异常事件可分为两类:
- Error(错误):Java虚拟机无法解决的严重问题。是系统中的错误,大多数与程序员的操作无关,程序员是不能改变和处理的,不需要关心这类错误。例如:StackOverflowError(栈溢出)和OOM(内存溢出)
 - Exception(异常): 在程序运行期间,发生的不被期望的事件,阻止了程序按照程序员的预期正常执行(开发过程中的语法错误和逻辑错误不是异常)。可以使用针对性的代码进行处理。例如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界、非法参数
 
异常分类
- 检查型异常:最具代表性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如用户要打开一个不存在的文件时引发的异常,这些异常在编译时不能被简单地忽略
 - 运行时异常:是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时忽略
 
异常示例
- 
java.lang.StackOverflowError 栈堆异常
Javapublic class Demo01 { public static void main(String[] args) { new Demo01().a(); //创建一个Demo01类的实例,并调用其a方法。 } public void a(){ b(); } public void b(){ a(); } } //在方法a中,调用了方法b;在方法b中,又调回了方法a。如此反复,陷入了一个无限循环。 - 
java.lang.ArithmeticException 算数运算异常
Javapublic class Demo02 { public static void main(String[] args) { System.out.println(11/0); } } 
异常体系结构
Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类,Throwable又派生出Error类和Exception类。 
异常处理机制
捕获异常
当程序中抛出一个异常后,如果该异常没有被捕获和处理,程序将终止。 可以使用try-catch语句来捕获异常。try块用于包含可能抛出异常的代码,而catch块用于捕获并处理异常。
语法格式
            
            
              java
              
              
            
          
          try {
    // 可能会抛出异常的代码
} catch (ExceptionType1 e) {
    // 处理ExceptionType1异常的代码
} catch (ExceptionType2 e) {
    // 处理ExceptionType2异常的代码
}finally {
    // 可选的finally块,无论是否发生了异常。这个块里的代码总是会被执行,除非程序中止
    //用于在发生异常或未发生异常时执行清理工作 
}
        在上述代码中:
catch块用于捕获并处理在try块中抛出的异常。可以有一个或多个catch块,每个块处理一种特定类型的异常。在每个catch块中,可以编写处理特定异常的代码。例如,可能想要记录异常信息,或者尝试以某种方式恢复程序的执行ExceptionType1和ExceptionType2是Java中预定义的异常类或自定义的异常类。它们表示特定类型的异常e是catch块中声明的变量,表示捕获的异常对象。可以使用这个变量来访问有关异常的信息,如异常的消息或堆栈跟踪
getMessage() 方法
getMessage() 方法定义在 Throwable 类中,因此它可以在任何从 Throwable 继承的类(如异常类)中直接使用,而不需要单独定义。当捕获到异常时,可以直接调用异常对象的 getMessage() 方法,以获取异常的描述信息
应用:当异常被捕获时,可以通过catch块中的参数e(或者自定义的异常变量名)来访问异常对象。e.getMessage()方法将返回一个字符串,其中包含有关异常的描述或详细信息。
示例
            
            
              java
              
              
            
          
          try {
    int[] arr = new int[5];
    arr[10] = 100; // 这将抛出一个ArrayIndexOutOfBoundsException异常
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组越界异常: " + e.getMessage());
    //这个异常被第一个catch块捕获,并输出一条包含异常消息的错误信息
} catch (Exception e) {
    System.out.println("其他异常: " + e.getMessage());
    //如果try块中的代码抛出其他类型的异常,它将被第二个catch块捕获,并输出一条包含异常消息的错误信息
}
        快捷键
- 按下
Ctrl+Alt+T快捷键,打开代码生成菜单 - 在菜单中选择"Surround With"选项
 - 在弹出的列表中选择"Try/Catch"选项
 - 按下Enter键,IDEA会自动在光标所在行的下一行插入一个try-catch代码块
 
抛出异常
除了捕获异常,还可以在程序中主动抛出异常 在Java中,可以使用throw关键字来显式地抛出一个异常。在try-catch语句中,一旦使用throw抛出一个异常,程序控制将立即转到最近的能够处理该异常的catch块
语法格式
            
            
              Java
              
              
            
          
          throw new 异常类型(参数);   //参数 是可选的,用于初始化异常对象
        当使用throw语句抛出异常后,程序将立即停止执行后面的代码,并跳转到能够处理该异常的catch块。如果没有找到合适的catch块来处理异常,程序将终止
示例
            
            
              java
              
              
            
          
          public class Example {
    public static void main(String[] args) {
        try {
            int[] arr = new int[5];
            throw new ArrayIndexOutOfBoundsException("数组越界异常");
            arr[10] = 100;   // 这行代码不会被执行,因为throw语句已经抛出了异常
        } catch (ArrayIndexOutOfBoundsException e) {   //程序控制立即转到第一个catch块
            System.out.println("捕获到数组越界异常: " + e.getMessage());  
            //并输出一条包含异常消息的错误信息
        } catch (Exception e) {
            System.out.println("捕获到其他异常: " + e.getMessage());
        }
    }
}
        自定义异常
- 创建自定义异常类,继承自Exception或Exception子类
 - 在方法中通过throw关键字抛出异常对象
 - 如果在抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常
 - 在出现异常方法的调用者中捕获并处理异常
 
            
            
              Java
              
              
            
          
          public class Demo02 {
    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            System.out.println("MyException->" + e); // 打印 MyException->MyException{detail=11}
//这里使用了异常对象e的toString()方法,该方法覆盖了从Exception类继承的方法,返回一个描述异常的字符串
        }
    }
    public static void test(int a) throws MyException {
    //定义了一个名为test的公共静态方法,它接受一个整数参数并可能抛出一个MyException异常
        if (a>10){
            throw new MyException(a);
//抛出一个新的MyException异常,并传递参数a作为详细信息。这将导致程序跳回到调用此方法的主方法中,并执行相应的catch块来处理这个异常
        }
    }
}
class MyException extends Exception{  //自定义异常类MyException的定义
    private int detail;
    public MyException(int detail) {
        this.detail = detail;
    }
    @Override
    public String toString() {  // 重写Exception类的toString方法,返回异常的字符串表示形式
        return "MyException{" + "detail=" + detail + '}';   // 返回包含detail值的字符串
    }
}