Java中try必须配catch或finally,合法结构仅三种:try-catch、try-finally、try-with-resources;catch需按继承顺序从具体到宽泛;checked异常须显式处理;禁用空catch;finally中return会覆盖catch返回值。

try catch 基本写法必须包含 catch 或 finally
Java 中 try 不能单独存在,必须配对 catch 或 finally。常见错误是只写 try { ... } 就结束,编译直接报错:error: 'try' without 'catch', 'finally', or resource declarations。
正确结构只有三种合法组合:
try { ... } catch (Exception e) { ... }try { ... } finally { ... }-
try (Resource r = ...) { ... } catch (Exception e) { ... } finally { ... }(带资源声明的 try-with-resources)
注意:catch 块必须按异常继承顺序从具体到宽泛排列,否则编译失败。比如先写 catch (IOException e),再写 catch (Exception e);反过来会提示 exception IOException has already been caught。
捕获 checked 异常必须显式处理
像 IOException、SQLException 这类 checked 异常,不处理就编译不过。你不能只抛出一个 new IOException() 而不包在 try catch 里,也不能在方法签名里漏掉 throws。
立即学习“Java免费学习笔记(深入)”;
典型场景:读文件时没加 try catch 或 throws:
FileReader fr = new FileReader("a.txt"); // 编译错误:unreported exception IOException
解决方式二选一:
- 用
try catch包住并处理:catch (IOException e) { System.err.println(e.getMessage()); } - 在方法签名中声明:
public static void readFile() throws IOException
别试图用 catch (Exception e) 一锅端来掩盖设计问题——这会让调用方失去对异常类型的感知,也违背 Java 的异常分类意图。
不要吞掉异常或空 catch 块
写成这样非常危险:
try {
doSomething();
} catch (Exception e) {
// 什么也不做
}
异常被静默吞掉,程序看似“正常”运行,但实际逻辑可能已中断,后续状态错乱,排查时毫无日志线索。
至少应做到以下之一:
- 记录日志:
logger.error("Failed to process item", e); - 重新抛出封装异常:
throw new RuntimeException("Processing failed", e); - 根据业务恢复逻辑,比如重试、降级、返回默认值
特别注意 catch (Throwable t) ——它连 OutOfMemoryError 都抓,而这类错误通常不该被捕获处理,强行 catch 反而阻碍 JVM 正确响应。
finally 中的 return 会覆盖 catch 里的 return
这是个容易踩坑的语义细节。如果 catch 块里有 return,但 finally 里也有 return,最终返回的是 finally 的值。
public static int getValue() {
try {
throw new RuntimeException();
} catch (Exception e) {
return 1;
} finally {
return 2; // 这个 return 生效,调用方拿到 2
}
}
同理,finally 中抛出异常也会覆盖 catch 中的异常。所以 finally 里尽量避免 return 或抛异常;真要清理资源,用 try-with-resources 更安全。
真正需要控制流程的地方,别依赖 finally 的执行顺序——它只保证执行,不保证“不干扰”。










