多态设计应以分派承担通用行为,辅以轻量级rtti处理子类特有逻辑;优先通过重写统一方法签名实现扩展,仅在必要时用instanceof安全转型,或用getclass()/isinstance()应对动态场景,并将类型逻辑封装进策略注册机制。

多态设计本身不排斥运行时类型检查,关键在于用得恰到好处——不是用来替代多态,而是补足多态无法覆盖的场景。真正灵活的扩展,是让多态分派承担通用行为,再用轻量级 RTTI 处理子类特有逻辑,二者协同而非互斥。
优先靠多态分派处理共性行为
把能统一抽象的行为,全部交给重写方法或接口实现。JVM 在运行时自动选择对应子类版本,无需人工判断类型。
- 定义统一方法签名(如 render()、calculateFee()),在父类或接口中声明
- 各子类按需重写,比如 PdfExporter 输出 PDF 格式,JsonExporter 输出 JSON 格式
- 调用方只操作 Exporter 类型引用,新增格式只需加子类,不改已有代码
用 instanceof 做安全、局部的类型突破
当确实需要访问某个子类独有的能力(比如 DatabaseConnection 的 getPoolSize() 或 HttpClient 的 getTimeoutMs()),才启用运行时检查。
- 必须先 if (obj instanceof SpecificType),再转型调用,避免 ClassCastException
- 只在必要位置使用,不用于主流程分支(例如不用它代替 pay() 这类核心行为)
- 配合注释说明“此处因 XXX 需求需访问子类特有 API”,便于后续重构
用 getClass() 或 Class.isInstance() 应对动态或精确匹配场景
当类型判断逻辑不能硬编码,或需排除继承关系时,比 instanceof 更合适。
- getClass() == Target.class:严格匹配当前类,不接受子类(如日志审计需区分原始创建类型)
- Target.class.isInstance(obj):效果同 instanceof,但支持变量传入类型,适合策略工厂、插件加载等动态场景
- 避免直接用 obj.getClass().getName().equals("xxx"),易出错且不可靠
把类型相关逻辑封装进策略或扩展点
随着子类增多,零散的 instanceof 会失控。此时应主动收口,把类型判断和行为绑定解耦。
- 引入 HandlerRegistry,按类类型注册专属处理器(如 Handler
) - 用 ServiceLoader 或 Spring 的 @Component 自动发现扩展实现
- 把 if-else instanceof 替换为查表或映射,使新增子类只需注册,不改调度逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











