异常处理是Java开发里最基础也最容易忽视的东西了。刚学的时候觉得try-catch就是写个模板代码,后来项目上线了才知道——异常处理做不好,线上出问题连排查都无从下手。这篇文章把Java异常体系的来龙去脉讲清楚。
Java异常处理详解
什么是异常?
异常就是程序运行时出的问题,会中断正常执行流程。在Java中,异常就是一个对象。要注意,异常和Error是两回事——Error是程序自己搞不定的(比如内存溢出),而异常是我们可以处理的。
异常的分类
受检异常(Checked Exception)
编译器要求必须处理的异常,继承自Exception(不包括RuntimeException)。
常见的有:IOException、SQLException、ClassNotFoundException、FileNotFoundException。
不处理的话编译就过不了,所以必须用try-catch兜着或者在方法上throws。
非受检异常(Unchecked Exception / RuntimeException)
编译器不强制处理的异常,继承自RuntimeException。
常见的有:NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException、IllegalArgumentException、ClassCastException。
异常层次结构
Throwable├── Error ← 程序搞不定的,别catch│ ├── OutOfMemoryError│ └── StackOverflowError└── Exception ├── RuntimeException ← 非受检,不用强制处理 └── IOException 等 ← 受检,必须处理异常处理机制
try-catch
try { int result = 10 / 0;} catch (ArithmeticException e) { System.out.println("算术异常:" + e.getMessage());}多个catch
子类异常在前,父类在后:
try { // ...} catch (NullPointerException e) { // 先捕获具体的} catch (Exception e) { // 再捕获通用的}finally
无论是否发生异常,finally都会执行。用来释放资源(关闭文件、数据库连接等)。
try { // ...} catch (Exception e) { // ...} finally { // 一定会执行}注意:finally里别用return,它会覆盖try/catch里的return值。
try-with-resources(Java 7+)
实现了AutoCloseable接口的资源可以自动关闭,不用写finally了:
try (FileReader reader = new FileReader("file.txt")) { // 读取文件} catch (IOException e) { // reader会自动关闭}throw 和 throws
throw:手动抛出异常throws:声明方法可能抛出的异常
public void checkAge(int age) { if (age < 0) { throw new IllegalArgumentException("年龄不能为负数"); }}
public void readFile(String path) throws IOException { // ...}自定义异常
继承Exception(受检)或RuntimeException(非受检):
public class BusinessException extends RuntimeException { private int errorCode;
public BusinessException(int errorCode, String message) { super(message); this.errorCode = errorCode; }
public int getErrorCode() { return errorCode; }}常见陷阱
- 捕获异常后什么都不做——这是最坑的,出了问题连日志都找不到
- 用异常做流程控制——比如用
ArrayIndexOutOfBoundsException判断数组越界,性能差不说,代码也难看 - 在finally里return——会覆盖try/catch的返回值
- 不释放资源——打开文件流忘了关,服务器上文件描述符被耗尽,应用直接挂了。这个我犯过,教训深刻
- 丢失原始异常信息——捕获异常后抛新异常,忘了把原始异常传进去
💡 实战贴士: 用try-with-resources替代try-finally来管理资源,代码更简洁,还能避免忘记关闭资源的问题。另外,日志记录异常时用
logger.error("消息", e),别用e.printStackTrace(),生产环境没人看控制台。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时






