Java中编译期异常由编译器在生成字节码前强制检查并报错,如IOException;运行期异常由JVM在执行字节码时检测非法状态抛出,如NullPointerException。

Java里区分编译期异常和运行期异常,关键看“谁在什么时候检查、谁在什么时候出错”。不是看代码写得对不对语法,而是看错误发生在生成字节码前还是执行字节码时。
编译期异常:javac一读就报错
这类异常也叫“受检异常(checked exception)”,编译器强制你处理——要么 try-catch,要么 throws 声明。它们通常来自外部不可控因素,比如文件不存在、网络断开、日期格式不对。
- 典型代表:IOException、SQLException、ClassNotFoundException、ParseException
- 触发时机:你在写完代码后点“编译”(javac 或 IDE 自动构建),编译器扫描到可能抛出这些异常的语句,立刻报错,不让你生成 .class 文件
- 例子:
FileReader fr = new FileReader("missing.txt");—— 编译器看到这行就标红,提示“Unhandled exception type FileNotFoundException”
运行期异常:代码能编过,一跑就崩
这类异常属于“非受检异常(unchecked exception)”,继承自 RuntimeException,编译器完全不管它有没有处理。它们大多暴露的是程序逻辑缺陷,比如空指针、越界、除零。
- 典型代表:NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException、IllegalArgumentException
- 触发时机:程序已成功编译、启动、执行到某一行才突然抛出,JVM 在运行中检测到非法状态,立即中断当前线程并打印堆栈
- 例子:
String s = null; s.length();—— 编译通过,但运行到第二行直接抛NullPointerException
一个简单判断口诀
写代码时留意 IDE 的提示:
立即学习“Java免费学习笔记(深入)”;
- 如果编辑器自动弹出“Add try/catch or declare exception”建议 → 这是编译期异常
- 如果写完没任何提示,但运行时报红、控制台打印 Exception 栈 → 这是运行期异常
- 如果连编译都通不过,报“cannot resolve symbol”或“incompatible types” → 这根本不是异常,是编译期错误(compile-time error),比如语法错、类型错、符号未定义
别混淆:泛型擦除是编译期行为,不是异常
像 List<String> 在编译后变成 List,这是编译器做的类型擦除,属于编译期转换,不会报错也不会抛异常。它和异常触发时机无关,但常被误当作“运行期才出问题”的例子——其实它压根不报错,只是运行时无法做泛型类型检查。


















