Java 常见异常梳理

Java 常见异常全面梳理(分类+含义+典型场景)

Java 异常体系核心分为 运行时异常(RuntimeException,非受检)编译时异常(Checked Exception 受检) ,前者编译期无需强制捕获,由程序逻辑错误导致;后者编译期必须显式捕获/抛出,由外部环境(如IO、网络、输入)异常导致。此外,还有错误(Error) 属于JVM层面严重问题,通常无需程序处理。
区分「运行时异常(预防为主)、受检异常(强制处理)、JVM错误(提前规避)」

一、运行时异常(RuntimeException)------ 逻辑错误主导,预防优先,捕获兜底

继承自java.lang.RuntimeException,编译期无需强制处理,多由代码逻辑不严谨导致,核心处理原则是通过严谨的代码逻辑从根源避免,仅对无法预防的场景做捕获兜底

1. NullPointerException(NPE)------ 开发最高频异常

  • 核心含义:调用空对象的方法/属性、对空对象执行集合/数组操作,或自动拆箱空包装类
  • 典型场景Object obj = null; obj.toString();Integer num = null; int n = num;、方法返回null未判空直接使用
  • 标准处理方式 (按优雅度排序,从基础到高级)
    1. 基础方案:显式判空,对所有可能为null的对象执行非空校验;
    2. 优雅方案:Java 8+ Optional类,包装可能为null的对象,避免手动判空;
    3. 校验方案:使用Objects.requireNonNull()做参数/对象非空校验,快速定位空指针源头;
    4. 开发规范:方法返回值尽量返回空集合/空对象 (如Collections.emptyList()),而非null,减少调用方判空成本。
  • 核心代码示例
java 复制代码
// 1. 显式判空
Object obj = getObj();
if (obj != null) {
    obj.toString();
}

// 2. Optional优雅处理(推荐,无嵌套判空)
Optional.ofNullable(getObj()).ifPresent(o -> o.toString()); // 仅当非空时执行
String res = Optional.ofNullable(getStr()).orElse("默认值"); // 空则返回默认值

// 3. 非空校验(参数/方法内对象,快速定位问题)
public void doWork(User user) {
    Objects.requireNonNull(user, "用户对象不能为空");
    Objects.requireNonNull(user.getName(), "用户名不能为空");
}
  • 避坑点 :切勿仅用if (obj != null)做多层嵌套判空(会导致代码臃肿),优先使用Optional。

2. ArrayIndexOutOfBoundsException ------ 数组操作专属

  • 核心含义:访问数组的索引超出有效范围(索引<0 或 索引>=数组长度)
  • 典型场景int[] arr = new int[3]; arr[3] = 10;、循环遍历数组时条件写为i <= arr.length
  • 标准处理方式
    1. 核心原则:遍历数组始终以arr.length为边界,循环条件用i < arr.length
    2. 根源规避:使用增强for循环遍历数组,无需手动操作索引,从源头避免越界;
    3. 前置校验:手动操作索引时,先校验索引合法性(index >= 0 && index < arr.length)。
  • 核心代码示例
java 复制代码
int[] arr = {1,2,3};
// 1. 增强for循环(推荐,无索引操作)
for (int num : arr) {
    System.out.println(num);
}

// 2. 手动索引操作(前置校验)
int index = 3;
if (index >= 0 && index < arr.length) {
    System.out.println(arr[index]);
} else {
    System.err.println("索引越界,合法索引0-" + (arr.length-1));
}

3. IndexOutOfBoundsException(含子类StringIndexOutOfBoundsException)

  • 核心含义:访问集合/字符串的索引超出有效范围,是数组越界的「集合/字符串版」
  • 典型场景List<String> list = new ArrayList<>(); list.get(0);"java".substring(5)
  • 标准处理方式
    1. 集合操作:遍历用增强for循环,手动获取元素前校验index < list.size()+集合非空(!list.isEmpty());
    2. 字符串操作:截取/获取字符前校验index < str.length()+字符串非空(!str.isBlank());
    3. 工具辅助:使用org.apache.commons.lang3.StringUtils/CollectionUtils,避免原生方法的越界问题。
  • 核心代码示例
java 复制代码
List<String> list = Arrays.asList("a", "b");
String str = "java";
int index = 4;

// 集合安全获取
if (!CollectionUtils.isEmpty(list) && index < list.size()) {
    System.out.println(list.get(index));
}

// 字符串安全截取(Apache工具类,越界会返回空/原字符串,无异常)
String sub = StringUtils.substring(str, 0, index); 

4. ClassCastException ------ 类型转换高频异常

  • 核心含义 :将对象强制转换为其实际运行时类型并非所属的类/接口(无继承/实现关系)
  • 典型场景Object obj = new Integer(10); String str = (String) obj;、泛型擦除后集合强转元素
  • 标准处理方式
    1. 前置判断:转换前用instanceof校验对象实际运行时类型,再执行强转;
    2. 简化方案:Java 14+ 模式匹配,一步完成「类型判断+强制转换」,简化代码;
    3. 根源规避:集合操作强制指定泛型 (如List<String> list = new ArrayList<>()),编译期拦截非目标类型元素。
  • 核心代码示例
java 复制代码
Object obj = new Integer(10);
// 1. 传统方式:instanceof判断+强转
if (obj instanceof String) {
    String str = (String) obj;
}

// 2. Java14+ 模式匹配(推荐,少一层代码)
if (obj instanceof String str) {
    System.out.println(str.length());
}

// 3. 泛型规避(从根源避免)
List<String> list = new ArrayList<>();
list.add("java");
// list.add(10); // 编译期直接报错,无法添加非String类型

5. InputMismatchException ------ Scanner输入专属

  • 核心含义java.util.Scanner读取数据时,输入数据类型与预期读取类型不兼容
  • 典型场景 :用scanner.nextInt()读整数,用户输入字符串("abc")、小数(3.14)
  • 标准处理方式 (核心:清空输入缓冲区,避免死循环
    1. 推荐方案:先判断再读取 ,使用Scanner的hasNextXxx()系列方法匹配读取方法(hasNextInt()对应nextInt());
    2. 兜底方案:捕获异常后,必须调用scanner.next()清空缓冲区的无效数据;
    3. 万能方案:先读取原始字符串,再通过包装类手动转换,配合try-catch处理。
  • 核心代码示例(推荐方案,无异常)
java 复制代码
Scanner scanner = new Scanner(System.in);
int num = 0;
while (true) {
    System.out.print("请输入整数:");
    if (scanner.hasNextInt()) {
        num = scanner.nextInt();
        break; // 输入合法,退出循环
    } else {
        System.err.println("输入错误,仅支持整数!");
        scanner.next(); // 关键:清空缓冲区的无效数据,避免死循环
    }
}

6. ArithmeticException ------ 数值计算错误

  • 核心含义 :算术运算中出现非法操作,整数除零/取模模数为0是最典型场景
  • 典型场景int a = 10 / 0;10 % 0(注:浮点数除零结果为Infinity,不会触发此异常)
  • 标准处理方式
    1. 前置校验:对除法/取模的除数/模数做非零校验,从根源避免;
    2. 异常兜底:捕获异常后,根据业务返回默认值或抛出自定义提示,避免程序崩溃。
  • 核心代码示例
java 复制代码
int a = 10, b = 0;
int res = 0;
// 前置校验(推荐)
if (b != 0) {
    res = a / b;
} else {
    System.err.println("除数不能为零");
    res = 0; // 业务默认值
}

// 异常兜底(无法提前校验的场景)
try {
    res = a / b;
} catch (ArithmeticException e) {
    System.err.println("计算失败:除数不能为零");
    res = 0;
}

7. IllegalArgumentException ------ 参数非法通用异常

  • 核心含义 :方法接收到不符合业务要求的非法参数,是自定义方法参数校验的标准异常
  • 典型场景 :方法要求参数>0却传入-1、要求非空字符串却传入空串、Collections.sort(null)
  • 标准处理方式
    1. 主动抛出:方法入口处做参数校验 ,参数不合法时主动抛出该异常,并携带明确的错误提示;
    2. 工具辅助:使用Objects/Apache Commons工具类简化参数校验,避免重复代码;
    3. 框架适配:Spring项目可使用@Valid/@NotBlank等注解做参数自动校验,无需手动判断。
  • 核心代码示例
java 复制代码
// 手动参数校验+主动抛出异常(推荐,语义清晰)
public void setAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄必须在0-150之间,当前值:" + age);
    }
    this.age = age;
}

// Spring项目注解校验(简化代码)
public void addUser(@Valid User user) {
    // User类中:@NotBlank(message = "用户名不能为空") private String name;
}

8. NumberFormatException ------ 数值格式转换错误

  • 核心含义:将非数值格式的字符串转换为int/double/long等数值类型时触发
  • 典型场景Integer.parseInt("123a");Double.parseDouble("3.14.5");、前端传参非数值字符串后端直接转换
  • 标准处理方式
    1. 异常捕获:转换时通过try-catch捕获异常,返回业务默认值或提示格式错误;
    2. 工具辅助:使用org.apache.commons.lang3.math.NumberUtils,转换失败返回默认值,无需手动捕获;
    3. 前置校验:转换前通过正则表达式 校验字符串是否为合法数值(如^\\d+$匹配整数)。
  • 核心代码示例
java 复制代码
String str = "123a";
// 1. try-catch兜底
int num1 = 0;
try {
    num1 = Integer.parseInt(str);
} catch (NumberFormatException e) {
    System.err.println("数值格式错误,默认值为0");
}

// 2. NumberUtils工具类(推荐,简化代码)
int num2 = NumberUtils.toInt(str, 0); // 转换失败返回默认值0
double num3 = NumberUtils.toDouble(str, 0.0);

9. ConcurrentModificationException ------ 集合并发修改错误

  • 核心含义 :单/多线程中,遍历集合的同时执行结构性修改(增/删/修改集合容量)
  • 典型场景 :增强for循环遍历List时调用list.remove()、多线程同时操作非线程安全集合(ArrayList/HashMap)
  • 标准处理方式 (分单/多线程场景)
    1. 单线程:使用迭代器(Iterator) 遍历并修改,调用it.remove(),这是集合遍历修改的标准方式;
    2. 多线程:替换为线程安全集合CopyOnWriteArrayList替代ArrayList、ConcurrentHashMap替代HashMap);
    3. 兜底方案:遍历前将集合转为数组,或遍历过程中收集需要修改的元素,遍历完成后统一处理
  • 核心代码示例
java 复制代码
List<String> list = new ArrayList<>();
list.add("a"); list.add("b"); list.add("c");

// 1. 单线程安全修改(迭代器)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if ("a".equals(it.next())) {
        it.remove(); // 无异常,标准方式
    }
}

// 2. 多线程安全集合(直接替换,无需修改业务代码)
List<String> safeList = new CopyOnWriteArrayList<>();
Map<String, String> safeMap = new ConcurrentHashMap<>();

10. UnsupportedOperationException ------ 不支持的操作

  • 核心含义 :调用了对象未实现/不支持的方法,多为只读/固定长度对象的修改操作
  • 典型场景Arrays.asList(arr).add(1);(该List为固定长度)、对Collections.unmodifiableList()执行增删
  • 标准处理方式
    1. 根源规避:若需修改数组转换的List,重新创建可修改集合new ArrayList<>(Arrays.asList(arr)));
    2. 开发规范:使用集合前确认其类型,避免对只读集合执行修改操作;
    3. 前置判断:通过集合的class判断是否为可修改类型(兜底方案)。
  • 核心代码示例
java 复制代码
String[] arr = {"a", "b"};
// 错误:固定长度List,无法修改
// List<String> list = Arrays.asList(arr);
// 正确:重新创建可修改ArrayList
List<String> list = new ArrayList<>(Arrays.asList(arr));
list.add("c"); // 正常执行

二、受检异常(Checked Exception)------ 外部环境异常,强制处理,资源释放

继承自java.lang.Exception(非RuntimeException子类),编译期必须通过try-catch捕获或throws声明抛出,多由程序外部环境异常导致(如文件不存在、网络断开),核心处理原则是强制捕获处理,核心操作是「释放资源+业务兜底」

1. IOException(及子类)------ IO操作核心异常(最常用)

  • 核心含义 :所有IO操作的通用异常父类,子类覆盖具体场景:FileNotFoundException(文件不存在)、SocketException(网络断开)、EOFException(文件提前结束)
  • 典型场景:文件读写、流的打开/关闭、网络数据传输、控制台输入流操作
  • 标准处理方式 (核心:保证IO资源100%释放
    1. 优雅方案:Java 7+ try-with-resources 语法(自动关闭实现AutoCloseable接口的资源,替代finally,推荐);
    2. 传统方案:try-catch-finally,在finally块中手动关闭资源(需判空,避免空指针);
    3. 业务兜底:捕获异常后记录日志,返回友好的业务提示(如"文件读取失败"),避免暴露底层异常。
  • 核心代码示例(try-with-resources 自动释放资源,推荐)
java 复制代码
// 流对象实现AutoCloseable,try代码块结束后自动关闭,无需手动finally
try (FileReader fr = new FileReader("test.txt");
     BufferedReader br = new BufferedReader(fr)) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    System.err.println("业务提示:文件不存在,请检查路径");
    log.error("文件读取失败,路径:test.txt", e); // 记录详细日志(含堆栈)
} catch (IOException e) {
    System.err.println("业务提示:文件读取失败");
    log.error("文件读写异常", e);
}
  • 关键子类FileNotFoundException(优先捕获,精准定位文件问题)、SocketException(网络IO,需增加重连逻辑)。

2. InterruptedException ------ 线程中断协作异常

  • 核心含义 :线程处于可中断阻塞状态 时,被其他线程调用interrupt()中断,是线程间的「协作中断信号」(非错误异常)
  • 典型场景 :线程执行Thread.sleep()/Object.wait()/CountDownLatch.await()/Thread.join()时被中断
  • 关键特性 :异常触发后,JVM会自动清除线程的中断状态isInterrupted()返回false),切勿空catch吞掉异常(并发编程大忌)
  • 标准处理方式 (核心三原则:恢复状态/释放资源/优雅终止,分3种场景)
    1. 工具方法场景 :捕获异常后恢复中断状态Thread.currentThread().interrupt())+ 向上抛出异常,让上层调用方处理;
    2. 线程入口场景 :捕获异常后立即释放资源 (关闭流/释放锁)+ 直接终止线程(return);
    3. 批量任务场景:恢复中断状态 + 跳过当前任务,让后续代码检测到中断并处理。
  • 核心代码示例(工具方法+线程入口,最常用)
java 复制代码
// 场景1:工具方法(不负责线程生命周期,向上抛出)
public void doBlockingWork() throws InterruptedException {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt(); // 恢复中断状态,让上层感知
        throw e; // 向上抛出
    }
}

// 场景2:线程入口(最终处理,释放资源+终止)
Thread worker = new Thread(() -> {
    FileWriter writer = null;
    try {
        writer = new FileWriter("log.txt");
        doBlockingWork(); // 调用工具方法
    } catch (InterruptedException e) {
        System.out.println("收到中断请求,开始优雅终止");
        // 步骤1:释放资源
        if (writer != null) {
            try { writer.close(); } catch (IOException ex) { log.error("资源释放失败", ex); }
        }
        // 步骤2:终止线程
        return;
    } catch (IOException e) {
        log.error("IO异常", e);
    }
});
worker.start();
worker.interrupt(); // 主线程触发中断

3. SQLException ------ 数据库JDBC操作专属

  • 核心含义:执行数据库操作(增删改查、连接、关闭)时触发,覆盖连接失败、SQL语法错误、表/字段不存在等场景
  • 典型场景:数据库地址/账号密码错误、SQL语句拼写错误、操作不存在的表、连接池耗尽
  • 标准处理方式 (核心:资源释放+事务回滚+隐藏敏感信息
    1. 资源管理:使用try-with-resources自动关闭Connection/Statement/ResultSet(均实现AutoCloseable),避免数据库连接泄漏;
    2. 事务处理:异常时执行事务回滚conn.rollback()),避免数据不一致;
    3. 日志与提示:记录详细日志 (含SQL语句、参数),返回通用业务提示(如"数据库操作失败"),避免暴露数据库地址/账号等敏感信息;
    4. 重试机制:对连接超时、网络抖动等临时异常,增加重试逻辑(配合Guava Retryer/Spring Retry)。
  • 核心代码示例
java 复制代码
String sql = "INSERT INTO user (name) VALUES (?)";
// try-with-resources 自动关闭数据库资源
try (Connection conn = DBUtil.getConnection();
     PreparedStatement pstmt = conn.prepareStatement(sql)) {
    conn.setAutoCommit(false); // 关闭自动提交,开启事务
    pstmt.setString(1, "test");
    pstmt.executeUpdate();
    conn.commit(); // 提交事务
} catch (SQLException e) {
    // 事务回滚
    if (conn != null) {
        try { conn.rollback(); } catch (SQLException ex) { log.error("事务回滚失败", ex); }
    }
    log.error("SQL执行失败,SQL:{}", sql, e); // 记录详细日志
    System.err.println("业务提示:数据保存失败,请稍后重试"); // 通用提示
}

4. ClassNotFoundException ------ 类加载异常

  • 核心含义 :JVM在类加载过程中,无法找到指定全限定名的类文件(包名+类名)
  • 典型场景 :反射加载类时类名写错(Class.forName("com.test.User"))、项目依赖缺失、classpath未包含该类
  • 标准处理方式
    1. 基础排查:检查类的全限定名是否拼写正确(包名、类名大小写);
    2. 环境检查:确认项目运行时的classpath包含该类的class文件/依赖包;
    3. 异常处理:捕获异常后记录详细日志(类名、classpath信息),返回明确的排查提示。
  • 核心代码示例
java 复制代码
try {
    Class<?> cls = Class.forName("com.test.User");
    Object obj = cls.newInstance();
} catch (ClassNotFoundException e) {
    log.error("类加载失败,类名:com.test.User,请检查类名/依赖", e);
    System.err.println("系统异常:类加载失败,请联系开发人员");
} catch (InstantiationException | IllegalAccessException e) {
    log.error("类实例化失败", e);
}

5. ParseException ------ 日期/字符串解析异常

  • 核心含义 :对日期、自定义格式字符串进行解析/格式化时,输入格式与指定格式不匹配
  • 典型场景SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); sdf.parse("2026/02/05")
  • 标准处理方式
    1. 根源规避:统一数据格式,前端传参做格式限制(如日期仅允许yyyy-MM-dd);
    2. 优雅方案:使用Java 8+ 新日期时间API(LocalDate/DateTimeFormatter),线程安全且抛出更友好的DateTimeParseException(运行时异常);
    3. 异常捕获:解析前校验输入格式,捕获异常后返回默认值或友好提示。
  • 核心代码示例(推荐新日期API,替代传统SimpleDateFormat)
java 复制代码
String dateStr = "2026/02/05";
// 传统方式(SimpleDateFormat,非线程安全)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
    Date date = sdf.parse(dateStr);
} catch (ParseException e) {
    System.err.println("日期格式错误,请按yyyy-MM-dd输入");
}

// Java8+ 新日期API(推荐,线程安全,异常更友好)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
    LocalDate date = LocalDate.parse(dateStr, formatter);
} catch (DateTimeParseException e) { // 运行时异常,无需强制捕获
    System.err.println("日期格式错误,请按yyyy-MM-dd输入");
}

三、JVM错误(Error)------ 系统层面严重问题,提前规避,无需处理

继承自java.lang.Error,属于JVM/系统层面的严重异常 ,程序无法捕获和恢复,一旦发生通常导致程序崩溃,核心处理原则是提前规避,通过代码优化/JVM调优/环境配置防止发生,无需在代码中手动捕获

1. OutOfMemoryError(OOM)------ 内存溢出

  • 核心含义:JVM堆内存、方法区、元空间等内存区域耗尽,无法为新对象分配内存
  • 典型场景 :无限循环创建大对象、集合存储大量数据未清理(内存泄漏)、JVM堆内存设置过小(-Xmx配置不合理)、静态集合持有大量对象引用
  • 标准规避方式
    1. 代码优化:及时释放无用对象引用(如集合使用后清空、避免静态集合存储业务数据),排查内存泄漏(使用MAT/JProfiler工具);
    2. JVM调优:合理设置堆内存参数(-Xms初始堆 = -Xmx最大堆,避免内存频繁扩容,如-Xms2G -Xmx2G),调整元空间大小(-XX:MetaspaceSize=256M);
    3. 业务优化:采用分页查询/流式处理替代全量加载数据,避免一次性将大量数据加载到内存。

2. StackOverflowError ------ 栈溢出

  • 核心含义 :JVM方法调用栈的深度超过最大值,无限递归是最典型、最常见的场景
  • 典型场景 :无限递归调用方法(public void test() { test(); })、方法调用链过长(多层级业务方法嵌套)
  • 标准规避方式
    1. 代码优化:杜绝无限递归 ,检查递归方法的终止条件 ,确保能正常退出;若递归层级过深,改为循环实现(根本解决方案);
    2. 调优辅助:调整JVM栈大小参数(-Xss,如-Xss1M),增大方法调用栈深度(谨慎使用,治标不治本);
    3. 代码重构:将过长的方法调用链拆分为多个独立方法,减少嵌套层级。
  • 避坑点 :切勿依赖调整-Xss解决问题,无限递归即使增大栈大小,最终仍会触发栈溢出。

3. NoClassDefFoundError ------ 类定义未找到

  • 核心含义编译期能找到类,但运行期JVM无法找到该类的字节码文件 (与ClassNotFoundException的核心区别:前者是运行期类加载失败,后者是编译/反射时类不存在)
  • 典型场景:编译后删除了类的class文件、依赖的第三方包编译期存在但运行期缺失、Maven/Gradle依赖包版本冲突
  • 标准规避方式
    1. 环境检查:确认项目运行时的classpath包含所有依赖包,编译后的class文件完整无缺失;
    2. 依赖管理:使用Maven/Gradle统一管理依赖,执行clean install清理并重新编译项目,避免依赖包缺失/冲突;
    3. 类加载器排查:避免自定义类加载器的加载范围冲突,确保类被JVM正确加载。

四、Java 常见异常速查表(含核心处理方式,快速查阅)

分类 异常名称 核心关键词 核心处理/规避方式
运行时异常 NullPointerException 空对象、自动拆箱 Optional包装/Objects非空校验/返回空对象而非null
ArrayIndexOutOfBoundsException 数组索引越界 增强for循环/索引前置校验/以length为边界
IndexOutOfBoundsException 集合/字符串索引越界 非空校验/以size/length为边界/Apache工具类辅助
ClassCastException 强制类型转换错误 instanceof判断/Java14+模式匹配/集合指定泛型
InputMismatchException Scanner输入类型不匹配 hasNextXxx()前置判断/清空输入缓冲区/先读字符串再转换
ArithmeticException 整数除零、非法算术运算 除数非零校验/try-catch兜底返回默认值
IllegalArgumentException 方法参数非法 方法入口校验/主动抛出异常/Spring注解校验
NumberFormatException 字符串转数值格式错误 NumberUtils工具类/正则校验/try-catch兜底
ConcurrentModificationException 集合并发修改 迭代器修改/线程安全集合/遍历后统一修改
UnsupportedOperationException 不支持的操作 重新创建可修改集合/避免修改只读集合
受检异常 IOException(及子类) 文件/流/网络IO操作 try-with-resources自动关资源/finally释放/日志+业务提示
InterruptedException 线程阻塞时被中断 恢复中断状态/释放资源/优雅终止/切勿吞异常
SQLException 数据库JDBC操作 自动关连接/事务回滚/详细日志/通用业务提示
ClassNotFoundException 反射/类加载找不到类 检查类名拼写/确认依赖完整/排查classpath
ParseException 日期/字符串解析格式不匹配 统一格式/Java8+新日期API/前置格式校验
JVM错误 OutOfMemoryError 内存溢出、OOM 排查内存泄漏/JVM堆调优/分页/流式处理/释放无用引用
StackOverflowError 栈溢出、无限递归 杜绝无限递归/递归改循环/调整-Xss/拆分长调用链
NoClassDefFoundError 运行期找不到类定义 检查classpath/重新编译项目/Maven/Gradle统一依赖管理

五、Java 异常处理通用最佳实践(所有场景均适用)

  1. 切勿空catch吞掉异常 :尤其是InterruptedException、IO异常、SQL异常,空catch会导致问题无法定位、资源泄漏、程序逻辑混乱;
  2. 异常处理粒度适中 :不要用一个try-catch捕获所有异常(如catch (Exception e)),按异常类型细分处理,便于精准定位问题;
  3. 资源释放是核心:涉及IO、数据库、网络连接等资源的操作,必须保证资源释放(优先使用try-with-resources);
  4. 日志记录要完整 :捕获异常时记录异常堆栈+业务上下文 (如参数、SQL语句),避免仅打印e.printStackTrace()
  5. 前端/用户提示要友好:隐藏底层异常细节(如数据库地址、SQL语句),返回通用的业务提示(如"操作失败,请稍后重试");
  6. 运行时异常以预防为主:通过判空、参数校验、索引检查等逻辑从根源避免,而非依赖try-catch;
  7. 自定义异常语义清晰 :复杂业务中自定义异常(继承Exception/RuntimeException),让异常更贴合业务场景(如UserNotExistException),便于统一处理。
  8. 运行时异常 :重点在「预防」,通过严谨的代码逻辑(判空、参数校验、索引检查、泛型使用)避免,是日常bug排查的主要对象;
  9. 受检异常 :重点在「处理」,编译期强制捕获/抛出,需根据业务场景做兜底(如IO异常关闭流、SQL异常回滚事务);
  10. Error :重点在「规避」,通过合理的JVM参数配置(如调整堆内存)、优化代码(避免无限递归)防止,程序无法处理;
  11. 异常处理原则 :切勿空catch吞掉异常(尤其是InterruptedException),异常处理的核心是「恢复状态、释放资源、优雅提示/终止」。

掌握以上异常的处理方式和通用原则,能大幅提升Java代码的健壮性和可维护性,快速定位并解决开发中的各类异常问题,同时避免因异常处理不当导致的资源泄漏、程序崩溃、数据不一致等严重问题。

相关推荐
sensen_kiss2 小时前
Jupter Notebook 使用教程
大数据·人工智能·python·学习·数据分析
独自破碎E2 小时前
已经 Push 到远程的提交,如何修改 Commit 信息?
开发语言·github
缘空如是2 小时前
基础工具之jsoup工具
java·jsoup·html解析
毕设源码-郭学长2 小时前
【开题答辩全过程】以 基于Nodejs的网上书店 为例,包含答辩的问题和答案
java·eclipse
多恩Stone2 小时前
【3D-AICG 系列-1】Trellis v1 和 Trellis v2 的区别和改进
人工智能·pytorch·python·算法·3d·aigc
you-_ling2 小时前
Linux软件编程:Shell命令
java·linux·服务器
数智工坊2 小时前
【数据结构-栈、队列、数组】3.3栈在括号匹配-表达式求值上
java·开发语言·数据结构
凌康ACG2 小时前
Warm-Flow国产工作流引擎入门
java·工作流引擎·flowable·warm-flow
lsx2024062 小时前
Bootstrap 插件概览
开发语言