用接口default方法定义稳定契约、sealed+permits锁定实现范围,可构建抗篡改、易演进、边界清晰的sdk骨架:契约层开放、实现层收敛、扩展点受控。

用接口 default 方法定义稳定契约,用 sealed + permits 锁定实现范围,两者结合能构建出抗篡改、易演进、边界清晰的 SDK 基础骨架。核心不在堆砌语法,而在分层控制:契约层开放、实现层收敛、扩展点受控。
用 default 方法固化公共行为,避免子类重复实现
SDK 中大量通用逻辑(如日志埋点、参数校验、序列化模板)不应由使用者自由重写,而应由 SDK 统一提供且禁止绕过。default 方法天然适合这一角色:
- 所有实现类自动继承统一行为,无需强制覆写;
- default 方法体不可被子类 override(除非显式重写),但可被 final 实现类“继承即生效”;
- 若需差异化处理,应通过 protected 抽象钩子方法(如 doBeforeExecute())留出窄口径扩展点,而非开放整个 public 方法。
密封接口 + permits 列出且仅列出 SDK 自研实现
定义行为契约的接口必须是 sealed,并通过 permits 明确限定实现者——这些实现类必须全部由 SDK 内部维护,不能是用户代码:
- permits 后只写 SDK 包内已存在的 final 类 或 sealed 类(如 HttpTransport、MockStrategy、RetryPolicyV2);
- 所有实现类与密封接口置于同一包(如 com.example.sdk.transport),且不加 public 修饰符(包私有);
- 模块系统中不导出该包(module-info.java 中 omit exports com.example.sdk.transport),外部连类名都看不到,更无法实现或继承。
将扩展入口收口为工厂方法 + 密封类型返回
用户不该 new 实现类,也不该实现接口。所有接入点必须返回密封接口类型,并由 SDK 控制实例来源:
- 提供静态工厂方法,如 TransportFactory.create(String type),内部根据 type 返回预定义的 final 实现;
- 返回类型声明为密封接口(如 Transport),而非具体类;
- 若需支持用户自定义策略,不开放 implements,而是提供 @FunctionalInterface 回调 或 配置驱动的 sealed 子类枚举值(如 RetryPolicy.STANDARD、RetryPolicy.EXPONENTIAL)。
利用编译期约束替代运行时防御
防腐不是靠 if (obj instanceof XXX) 拦截,而是让非法代码根本编译不过:
- 用户代码若尝试 implements Transport,编译器直接报错:“class is not listed in the permits clause”;
- 用户若试图继承 SDK 的 sealed 实现类(如 class MyHttp extends HttpTransport),因 HttpTransport 是 final,编译失败;
- default 方法中可加入 Objects.requireNonNull(this.getClass().getModule()) 校验调用方是否来自预期模块,作为反射绕过的兜底。











