子类中extends与implements可见性及JMockit未重写方法调用报错问题
为什么JMockit调用未重写方法的D实例会报错?
这个问题其实涉及Java接口实现的隐式规则,以及JMockit框架对方法归属的特殊处理逻辑,咱们一步步拆解清楚:
一、先搞懂正常编译执行的逻辑
首先看你的代码结构:
- 接口
A定义了public void doSomething(),这是一个默认public的抽象方法。 - 抽象类
B虽然没实现A,但它定义了一个签名完全匹配、访问权限同为public的doSomething()方法。 - 当
C同时extends B和implements A时,Java的规则是:只要父类提供了签名匹配、权限足够的方法,就自动满足接口的契约——也就是说B的doSomething()直接替C完成了A接口的方法实现,哪怕C是抽象类也没问题。 - 最后
D继承C,自然继承了B里的doSomething()实现,所以正常调用完全没问题。
简单说:Java允许子类通过父类继承的方法来满足接口的实现要求,不需要自己显式写一遍。
二、JMockit报错的核心原因
JMockit这类字节码操作框架,在处理方法的时候,是盯着方法的归属来源来识别的,不是单纯看签名:
- 对于
D实例来说,doSomething()有两个“身份”:一个是从B继承来的类方法,另一个是A接口要求的契约方法。 - 正常Java运行时会把这两个“身份”合并成一个实际的实现,但JMockit不会——它会认为
A接口的方法需要由C或D直接实现,而不是靠父类B的继承来满足。当你调用D的doSomething()时,JMockit找不到C/D中直接对应A接口的方法实现,就会抛出错误。
三、extends与implements的可见性细节
这里要明确两个关键的可见性规则:
- 继承方法的可见性传递:
B的doSomething()是public,所以子类C、D继承后,方法的可见性依然是public,完全符合A接口对方法权限的要求(接口方法默认public,实现类的对应方法不能是更低权限)。这也是正常代码能跑通的基础。 - 接口实现的隐式vs显式:Java允许隐式通过父类方法满足接口,但JMockit这类框架更认可显式的接口实现——也就是在直接实现接口的类(这里是
C)里,显式重写接口方法并调用父类实现。
一个快速解决办法
如果要让JMockit正常工作,只需要在C中显式重写doSomething(),明确关联接口方法和父类实现:
public abstract class C extends B implements A{ @Override public void doSomething() { super.doSomething(); } }
这样JMockit就能明确识别到C是直接实现了A的doSomething()方法,调用D实例的该方法时就不会报错了。
内容的提问来源于stack exchange,提问作者123_xyz
相关产品推荐
相关产品推荐

