Java异常处理:从入门到放弃?(看完保你绝不放弃!)

一、为什么要学异常?(血的教训预警)

刚学Java那会儿,我在控制台看到这样的报错:
Exception in thread "main" java.lang.NullPointerException
当时整个人都懵了!就像打游戏突然黑屏,完全不知道哪里出问题(现在想想真是菜得真实😂)。后来才知道——不会处理异常的程序员,写出来的代码比定时炸弹还危险!

举个真实案例:
某电商系统在用户支付时,因为没处理NumberFormatException(数字转换异常),导致凌晨2点整个支付模块崩溃。第二天技术总监在晨会上直接发飙:“连基础异常都不处理,你们代码是纸糊的吗?!”

二、异常分类图鉴(必看干货)

1. Error:系统级暴击

public class SystemCrash {
    public static void main(String[] args) {
        int[] arr = new int[Integer.MAX_VALUE]; // 直接触发OutOfMemoryError
    }
}

这类错误(如OutOfMemoryErrorStackOverflowError)就像电脑主板烧了——程序员根本处理不了,只能靠JVM或运维人员抢救。

2. Exception:代码界的感冒发烧

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(假装这里有张图:Checked Exception和Unchecked Exception的对比表)

▶ Checked Exception(编译时异常)
  • 特点:编译器会强制检查,不处理不让编译
  • 常见类型:
    • IOException(文件找不到啦)
    • SQLException(数据库抽风啦)
    • ClassNotFoundException(类失踪啦)
▶ Unchecked Exception(运行时异常)
  • 特点:编译器不检查,运行时才会爆炸
  • 常见类型:
    • NullPointerException(空指针,新手的噩梦!)
    • ArrayIndexOutOfBoundsException(数组越界)
    • ArithmeticException(数学老师气哭的除零错误)

三、异常处理三板斧(附实战代码)

第一式:try-catch-finally(经典永流传)

try {
    FileInputStream fis = new FileInputStream("不存在的文件.txt");
} catch (FileNotFoundException e) {
    System.out.println("文件呢???");  // 输出友好提示
    e.printStackTrace();              // 打印堆栈轨迹(调试必备!)
} finally {
    System.out.println("无论成败,都要执行的代码!");
    // 比如关闭数据库连接(重要!重要!重要!)
}

避坑指南

  • finally块永远会执行(除非JVM崩溃)
  • JDK7+推荐用try-with-resources,自动关流美滋滋

第二式:throws(甩锅大法)

public void readFile() throws IOException {
    // 把异常抛给上层调用者处理
    Files.readAllLines(Paths.get("神秘文件.xxx"));
}

适用场景

  • 当前方法不知道如何处理
  • 需要统一异常处理的框架级代码

第三式:自定义异常(高端玩法)

// 继承RuntimeException创建自定义异常
class MoneyNotEnoughException extends RuntimeException {
    public MoneyNotEnoughException(String message) {
        super("余额不足警告!" + message);
    }
}

// 使用示例
void pay(double money) {
    if(balance < money) {
        throw new MoneyNotEnoughException("当前余额:" + balance);
    }
}

设计原则

  • 业务异常建议继承RuntimeException
  • 异常命名要见名知义,比如InvalidUserException

四、异常处理四大禁忌(血泪史总结)

❌ 禁忌1:捕获异常后不作为

try {
    // 可能出错的代码
} catch (Exception e) {
    // 什么都不写!(这是犯罪!)
}

后果:错误被静默吞噬,后期调试想撞墙

❌ 禁忌2:捕获Throwable

try {
    // 业务代码
} catch (Throwable t) {  // 把Error也捕获了!
    // 会导致OOM等严重问题被掩盖
}

❌ 禁忌3:在循环里捕获异常

for (int i=0; i<100; i++) {
    try {
        // 可能出错的代码
    } catch (Exception e) {
        // 循环内捕获影响性能
    }
}

改进方案:把try-catch移到循环外层

❌ 禁忌4:日志记录不当

catch (SQLException e) {
    logger.error("出错啦:" + e);  // 错误!丢失堆栈信息
    logger.error("数据库异常", e); // 正确写法!
}

五、高频面试题直击(附答案)

Q1:final、finally、finalize的区别?

  • final:修饰符(类不可继承/方法不可重写/变量不可修改)
  • finally:异常处理必执行代码块
  • finalize:Object类中的垃圾回收方法(JDK9已废弃)

Q2:throw和throws的区别?

  • throw:在方法内主动抛出异常对象
  • throws:在方法声明中标明可能抛出的异常类型

Q3:try-catch-finally的执行顺序?

  1. 执行try块
  2. 若有异常进入catch块
  3. 无论是否异常都执行finally块

六、总结提升路线

  1. 新手阶段:掌握try-catch-finally基础用法
  2. 进阶必备:理解异常分类和继承体系
  3. 高手之路
    • 学会使用Throwable.getCause()追踪根本原因
    • 掌握Thread.setDefaultUncaughtExceptionHandler全局异常处理
    • 研究Spring的@ControllerAdvice统一异常处理

最后送大家一句话:优秀的异常处理不是让程序永不报错,而是让错误发生时,能像老司机一样从容处理! 🚗💨

(本文示例代码已通过JDK17测试,建议边看边动手实践)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值