JJava 知识库
JAVA INTERVIEW

高频面试题

Java基础基础约 3 分钟

要接入十几家支付渠道,每家流程相似但细节不同,你会用接口、抽象类还是组合来设计?

参考回答约 3 分钟 · 口语表达
先说结论

这个问题我会先说项目结论:接口描述一组能力和契约,适合让无关类型获得统一行为;抽象类描述同一类对象的共同骨架,可以保存实例状态、构造逻辑和受保护的复用实现。类只能继承一个父类,却可以实现多个接口。 现代接口可以有 default、static 和私有方法,但不能承担普通可变实例状态;

01

我会先交代项目背景和选型结论。从类型关系、状态复用、默认方法和演进能力选择接口或抽象类。接口描述一组能力和契约,适合让无关类型获得统一行为;抽象类描述同一类对象的共同骨架,可以保存实例状态、构造逻辑和受保护的复用实现。类只能继承一个父类,却可以实现多个接口。 现代接口可以有 default、static 和私有方法,但不能承担普通可变实例状态;抽象类可以定义字段、构造器和非公开模板方法。

02

具体落地时,我会沿着实际调用链来讲。沿着「识别变化维度 → 抽取能力契约 → 决定是否共享状态 → 选择继承或组合 → 通过实现完成替换」观察输入、状态与输出,这些阶段都可以从日志、指标或源码里验证。 识别变化维度 设计开始先区分“是什么”与“能做什么”,避免仅因代码相似就建立脆弱继承关系。 抽取能力契约 接口适合表达跨层能力和替换点,一个类型可以实现多个接口,调用方只依赖最小契约。 java.util.AbstractList:骨架实现如何复用最小原语。 java.util.ServiceLoader:接口作为插件发现边界。 我会先确认请求实际走到了哪条路径,再用运行数据验证,不会只看类名或配置猜测。

03

参数和容量不能靠默认值,我会结合业务量来定。用一个新增渠道验证扩展:若需要修改基类多个 if 或空实现无关方法,记录为接口隔离失败;再用替身实现运行契约测试。

04

效果要用数据证明,线上问题也要能闭环。固定输入和基线 先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「实现类空方法比例」为主基线,记录值应满足「目标为 0」;同时保存 实现类数量与变更频率、基类条件分支数量,使后续变化能够回到同一时间轴比较。 所有支付方式继承同一个抽象基类后,二维码、银行卡和余额支付的差异被迫塞进条件分支。重构为支付接口、独立能力接口和可组合的风控/路由策略后,共享流程留在编排器,不再要求每个子类拥有无关状态。 把工具方法相似误判为 is-a 关系:实现类数量与变更频率:把胖接口拆成支付、退款、查询能力。 默认方法冲突未明确解决:基类条件分支数量:共享流程移到编排器而非可变基类。

05

最后我会主动说明这个方案不适合什么场景。方案:更适合的场景:主要收益:代价与边界。 接口:跨实现稳定契约和多能力组合:低耦合、便于替换与测试:不能自然承载实例状态。 抽象类:同族对象共享受控状态与模板流程:可复用字段和部分实现:单继承且容易形成脆弱基类。 组合与委托:行为可独立变化或运行时替换:职责清晰、扩展灵活:对象数量和协作关系更多。 选型至少带上 对象创建率、调用频次、输入规模和 API 边界,并用上面的量化基线验证;未知数据应明确为待测假设。