Java接口抽象方法未显式重写却可正常调用的原因咨询
核心原因
你的基础认知没有问题:接口的抽象方法必须被重写实现后才能实际执行,你观察到的现象是Java多态机制下编译期静态类型和运行时实际类型分离导致的,你目前只追溯到了变量的声明类型,没有定位到变量实际持有的对象实例。
- 编译阶段:编译器只检查变量的静态类型(也就是代码里显式声明的类型)中是否存在待调用的方法。这里
context的静态类型是LinkDiscoveryContext接口,只要接口中声明了deviceService()方法,编译就可以正常通过,不会校验方法的具体实现。 - 运行阶段:JVM会读取变量实际指向的对象实例的运行时类型,这个类型一定是实现了
LinkDiscoveryContext接口、重写了全部接口抽象方法(包括deviceService())的具体类,程序运行时实际执行的是这个具体类中重写后的方法逻辑,不会执行接口中无方法体的抽象定义。
你看到的逻辑可以用最小代码示例复现:
// 对应源码中的LinkDiscoveryContext接口 interface CustomContext { // 对应接口中声明的抽象方法deviceService() DeviceService deviceService(); } // 接口的具体实现类,这部分就是你目前没有追溯到的逻辑 class CustomContextImpl implements CustomContext { // 按要求重写接口抽象方法 @Override public DeviceService deviceService() { return new DeviceServiceImpl(); } } public class LinkDiscovery { // 对应你找到的成员变量声明,静态类型为接口 private final LinkDiscoveryContext context; // 变量实际赋值逻辑,final修饰的成员变量会在对象初始化时完成赋值 // 如果项目用了Spring等依赖注入框架,这个赋值过程可能由框架自动完成,没有显式new的代码 public LinkDiscovery(LinkDiscoveryContext context) { // 这里传入的实际是CustomContextImpl类的实例,只是用接口类型接收 this.context = context; } public void process() { // 编译时校验LinkDiscoveryContext存在deviceService()方法即放行 // 运行时实际执行传入的实现类中重写的deviceService()逻辑 DeviceService deviceService = context.deviceService(); } }
后续排查方向
你只需要顺着context变量的赋值链路查找即可:
- 排查该final成员变量的赋值入口:可能在类构造方法、实例初始化代码块中,也可能是依赖注入框架在项目启动时自动注入实现类实例
- 找到赋值时传入的实际对象类型后,进入对应类就能查到
deviceService()的具体实现逻辑
补充:如果是基于依赖注入框架开发的项目,接口实现类可能被框架生成动态代理对象,不会在业务代码中出现显式实例化实现类的语句,你可以直接搜索项目中所有
implements LinkDiscoveryContext的类,就能找到对应的方法实现。
内容的提问来源于stack exchange,提问作者Desmond Kang
相关产品推荐
相关产品推荐

