ioexception是受检异常,编译器强制要求捕获或声明,否则编译失败;它属于可预见、可恢复的外部错误,需显式处理,而runtimeexception子类则无需强制处理。
因为 ioexception 是受检异常(checked exception),java 编译器在编译阶段就会强制检查它是否被处理——不捕获、不声明,代码直接编译失败。
这是 Java 的设计选择,不是语法限制
Java 把异常分为两类:
-
受检异常:继承自
Exception,但不是RuntimeException的子类,比如IOException、SQLException。它们代表外部环境可能出错(磁盘满、网络断、文件不存在),可预见、可恢复,所以必须显式应对。 -
非受检异常:继承自
RuntimeException(如NullPointerException、ArrayIndexOutOfBoundsException),属于编程逻辑错误,编译器不强制处理。
不处理会怎样?
写这样一行代码:
FileReader reader = new FileReader("missing.txt");如果没用 try-catch 包裹,也没在方法签名加 throws IOException,javac 会报错:
这不是警告,是编译中断——程序根本跑不起来。
throws 和 try-catch 各有什么用?
-
throws是“甩手”:告诉调用者“我这里可能出 I/O 问题,你来管”。适合工具方法、底层封装,比如一个读配置的工具类方法可以声明public static String readConfig() throws IOException。 -
try-catch是“接手”:在当前层做具体应对,比如提示用户重试、切换备用路径、记录日志并返回友好错误。业务入口(如 Controller 方法)通常需要在这里做决策,而不是继续往上抛。
常见误区提醒
- 用了 try-with-resources 不等于处理了异常:它只保证资源关闭,
readLine()抛出的IOException仍需捕获或声明。 -
catch (IOException e) { e.printStackTrace(); }不算有效处理:控制台输出在生产环境不可见,也没做任何恢复动作,相当于假装看不见。 - 别在循环里对每次 I/O 操作都单独 try-catch:容易掩盖部分失败,导致数据不一致却无感知。











