本文包含异常概念、体系分类、处理方式、自定义异常四大部分。

一、什么是异常

异常就是Java程序在编译或运行过程中出现的错误,会导致程序非正常终止。

开发中最常见的异常场景:

  1. 数组索引越界:访问了数组不存在的下标
  2. 算术异常:除数为0
  3. 空指针异常:调用null对象的方法
  4. 文件不存在:读取本地不存在的文件
// 常见运行时异常示例
public class ExceptionTest {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30};
        System.out.println(arr[3]); // 数组索引越界异常
        System.out.println(10 / 0); // 算术异常
        String str = null;
        System.out.println(str.length()); // 空指针异常
    }
}

异常的核心作用

  1. 定位BUG:异常信息会精准打印错误位置和原因,是调试程序的关键
  2. 流程通知:作为方法的特殊返回值,告诉调用者方法执行失败的原因

二、Java异常完整体系

Java中所有异常和错误的根类是 java.lang.Throwable,整体分为两大分支:

1. Error(系统级错误)

属于JVM底层的严重问题(如内存溢出、系统崩溃),也无法通过代码处理。

2. Exception(程序异常,开发核心处理对象)

程序运行/编译中可预见的错误,我们所有异常处理都围绕这个类展开,又细分为运行时异常编译时异常

三、异常的两大分类

1. 运行时异常(RuntimeException)

  • 定义:RuntimeException 及其所有子类
  • 特点:编译阶段不报错,运行时才触发
  • 常见示例:数组越界、空指针、算术异常、类型转换异常

2. 编译时异常(受检异常)

  • 定义:非 RuntimeException 的Exception子类
  • 特点:编译阶段强制报错,必须处理才能运行
  • 常见示例:日期解析异常、文件读取异常、IO流异常
// 编译时异常示例(必须处理,否则编译失败)
import java.text.SimpleDateFormat;
import java.util.Date;

public class CompileException {
    public static void main(String[] args) throws Exception {
        String time = "2024-07-09";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date date = sdf.parse(time); // 日期解析异常(编译时异常)
    }
}

四、异常的两种核心处理方式

Java提供了抛出异常捕获异常两种处理方案,开发中可根据场景灵活使用。

1. 抛出异常(throws)

  • 作用:方法内部不处理异常,抛给调用者处理
  • 语法:在方法声明后添加 throws 异常类名
  • 简化写法:直接抛出 Exception 接收所有异常
// 抛出异常示例
public class ThrowException {
    public static void main(String[] args) throws Exception {
        // 调用者接收异常,也可继续抛出
        testException();
    }

    // 方法抛出异常,交给上层处理
    public static void testException() throws Exception {
        int num = 10 / 0;
    }
}

2. 捕获异常(try...catch)

  • 作用:直接拦截并处理异常,保证程序不终止
  • 语法:

    try {
        // 可能出现异常的代码
    } catch (异常类型 变量名) {
        // 异常处理逻辑
    }
  • 简化写法:catch (Exception e) 捕获所有异常
// 捕获异常示例
public class TryCatchException {
    public static void main(String[] args) {
        try {
            int num = 10 / 0;
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常堆栈信息
            System.out.println("程序出现异常,已处理!");
        }
        // 异常处理后,程序继续执行
        System.out.println("程序正常结束");
    }
}

五、自定义异常

Java内置的异常类无法覆盖所有业务场景(如年龄非法、手机号格式错误),此时需要自定义异常来管理业务错误。

自定义异常的两种类型

1. 自定义编译时异常

  • 继承:Exception
  • 特点:编译强制处理,提醒严格
// 自定义编译时异常
public class AgeIllegalException extends Exception {
    // 无参构造
    public AgeIllegalException() {}
    // 带异常信息的构造
    public AgeIllegalException(String message) {
        super(message);
    }
}

2. 自定义运行时异常

  • 继承:RuntimeException
  • 特点:编译不报错,运行触发,开发更常用
// 自定义运行时异常
public class AgeIllegalRuntimeException extends RuntimeException {
    public AgeIllegalRuntimeException() {}
    public AgeIllegalRuntimeException(String message) {
        super(message);
    }
}

自定义异常使用示例

public class CustomExceptionTest {
    public static void main(String[] args) {
        try {
            saveAge(300); // 传入非法年龄
        } catch (AgeIllegalException e) {
            e.printStackTrace();
            System.out.println("年龄校验失败!");
        }
    }

    // 业务方法:校验年龄并抛出自定义异常
    public static void saveAge(int age) throws AgeIllegalException {
        if(age < 1 || age > 200){
            throw new AgeIllegalException("年龄非法,范围必须是1-200");
        }
        System.out.println("年龄保存成功:" + age);
    }
}

六、企业级异常处理实践

  1. 分层抛出,统一捕获
    底层方法不处理异常,全部向上抛出,最外层统一捕获,打印日志并返回友好提示
  2. 异常重试修复
    针对用户输入错误等场景,捕获异常后引导用户重新输入,保证程序不中断
// 异常重试修复示例
import java.util.Scanner;

public class ExceptionRetry {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                System.out.print("请输入商品价格:");
                double price = sc.nextDouble();
                System.out.println("价格设置成功:" + price);
                break;
            } catch (Exception e) {
                System.out.println("输入格式错误,请重新输入数字!");
                sc.next(); // 清空错误输入
            }
        }
    }
}

七、总结

  1. 异常根类 Throwable,分 Error(无需处理)和 Exception(开发处理)
  2. 异常分类:运行时异常(编译不报错)、编译时异常(编译强制处理)
  3. 处理方式:throws 抛出(上层处理)、try...catch 捕获(自行处理)
  4. 自定义异常:继承 Exception(编译时)/RuntimeException(运行时)
  5. 开发规范:底层抛异常,上层统一捕获,避免程序崩溃

标签: none

添加新评论