构造代码块不能声明throws,受检异常必须由构造方法声明或在块内捕获并转为运行时异常;因构造代码块非方法,无签名,无法添加throws子句,故需将初始化逻辑移至构造方法并声明异常,或用try-catch包装为runtimeexception。

构造代码块(即非静态初始化块)中抛出受检异常(checked exception),不能直接在构造代码块里 throw,因为 JVM 不允许构造代码块声明 throws;它必须由 enclosing 构造方法来统一处理或声明。
构造代码块本身不能声明 throws
Java 语法规定:构造代码块({ ... })不是方法,没有签名,无法添加 throws 子句。若其中调用可能抛出受检异常的方法(如 Files.readAllLines(...)),编译器会报错:
解决方案:把异常转移到构造方法中声明
核心思路是——将构造代码块中的逻辑移到构造方法内部,并在构造方法上用 throws 声明该异常。构造代码块的职责本就是初始化,而初始化若涉及 I/O、反射等高风险操作,更适合显式交由构造方法管控。
- 删除原构造代码块,把初始化逻辑写进构造方法体
- 在构造方法签名后加上
throws XxxException - 调用方必须处理该异常(try-catch 或继续向上 throws)
示例对比
❌ 错误写法(编译不通过):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
class ConfigLoader {
private final List<string> lines;
{
// 编译错误:未处理的受检异常
lines = Files.readAllLines(Paths.get("config.txt"));
}
public ConfigLoader() {}
}</string>
✅ 正确写法(异常由构造方法声明):
class ConfigLoader {
private final List<string> lines;
public ConfigLoader() throws IOException {
this.lines = Files.readAllLines(Paths.get("config.txt"));
}
}</string>
替代方案:在构造代码块内捕获并包装为运行时异常
如果不想让调用方强制处理,可将受检异常转为 RuntimeException(如 IllegalArgumentException 或自定义运行时异常):
- 用
try-catch捕获受检异常 - 重新抛出非受检异常,并附带原始异常作为 cause
- 这样构造代码块可正常执行,且无需修改构造方法签名
{
try {
lines = Files.readAllLines(Paths.get("config.txt"));
} catch (IOException e) {
throw new RuntimeException("Failed to load config", e);
}
}
不复杂但容易忽略:构造代码块 ≠ 构造方法,它没有异常声明能力,所有受检异常最终都要落到构造方法头上,或被主动转成非受检异常。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










