子类构造器必须遵守父类构造器的异常契约:只能声明相同或更具体的受检异常、捕获后转为运行时异常,或内部消化;禁止扩大异常范围,推荐捕获后包装为RuntimeException并保留cause。

子类构造器本身不继承父类构造器,但必须显式或隐式调用父类构造器。如果父类构造器声明了受检异常(checked exception),子类构造器就得合规处理——不能抛出更宽泛的异常,否则编译失败。
子类构造器必须匹配父类构造器的异常契约
父类构造器若声明 throws ParseException,子类构造器只能:
- 在自己的 throws 中声明 相同异常(如 throws ParseException)
- 声明该异常的 子类(如 throws DateTimeParseException,前提是它是 ParseException 的子类)
- 用 try-catch 捕获并转为运行时异常(如 throw new RuntimeException(e))
- 完全不抛出——即内部消化异常(比如记录日志、设默认值、静默降级)
不能直接扩大异常范围
以下写法全部非法:
- throws Exception(比 ParseException 宽)
- throws IOException(与 ParseException 无关,无继承关系)
- throws Throwable(顶层,绝对禁止)
编译器会报错:“unreported exception … must be caught or declared”,本质是破坏了构造链的异常契约。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
推荐做法:优先捕获 + 包装为 RuntimeException
多数场景下,构造失败属于初始化阶段的严重问题,不适合让调用方强制处理检查异常。更自然的做法是:
- 用 try-catch 拦住父类构造器抛出的受检异常
- 包装成 unchecked 异常(如 RuntimeException 或自定义运行时异常)再抛出
- 保留原始异常作为 cause,便于排查
例如:
public MySubClass() {<br> try {<br> super(); // 可能抛 ParseException<br> } catch (ParseException e) {<br> throw new IllegalStateException("Failed to initialize parent", e);<br> }<br>}
谨慎调整父类构造器签名
如果多个子类反复遇到此约束,说明父类设计可能过于严格。可考虑:
- 将父类构造器的受检异常改为运行时异常(需评估影响范围)
- 提供无异常的替代构造器(如 static factory 方法)
- 把易出错逻辑移到 init() 方法中,由子类按需调用并处理
这类改动牵涉所有子类和调用方,务必做兼容性评估。

















