为何Java中接口与父类同名方法无歧义,同名变量却存在歧义?
为什么继承类并实现接口时,同名方法无冲突但同名变量会出现歧义?
这问题问到点子上了!其实本质是Java对于方法重写/实现和静态成员变量的规则差异导致的,咱们分开说:
一、同名方法为什么没问题?
先看你的第一个代码例子:
interface A { void test(); } class B { public void test() { System.out.println("Test"); } } public class MultipleLevelInheritance extends B implements A { public static void main(String[] args) { new MultipleLevelInheritance().test(); } }
这里的关键逻辑是:
- 接口A中的
test()方法,默认是public abstract(Java 8及以后如果是默认方法则是public default,但这里是抽象方法); - 父类B中的
test()是public修饰的,访问权限不低于接口方法的要求; - 当子类
MultipleLevelInheritance继承B时,自动继承了B的test()方法,而这个方法的签名完全匹配接口A的test()方法。Java会认为子类已经通过继承父类的方法,间接完成了接口的实现要求,相当于这个方法同时满足了父类继承和接口实现的需求,自然不会有冲突。
简单说:方法可以通过继承来“复用实现”满足接口要求,而且Java的方法重写规则允许这种情况,不会认为是冲突。
二、同名变量为什么会报歧义?
再看变量的例子:
interface A { int a = 10; } class B { public static int a = 9; } public class MultipleLevelInheritance extends B implements A { public static void main(String[] args) { System.out.println(a); //The field a is ambiguous } }
这里的核心原因是接口的变量本质是静态常量:
- 接口里定义的变量,不管你写没写修饰符,Java都会自动加上
public static final,所以A.a其实是public static final int a = 10;; - 父类B中的
a是public static(哪怕你改成public static final,它也是属于B类的静态常量); - 静态成员变量是和所属的类/接口直接绑定的,不存在“重写”或“覆盖”的概念——子类继承父类的静态变量是“隐藏”,但这里同时从B和A拿到了两个同名的静态变量,它们是完全独立的两个成员。当你直接写
a时,编译器无法判断你要引用的是B.a还是A.a,只能抛出歧义错误。
哪怕把B中的a设为final也没用,因为这时候两个都是public static final的静态常量,但归属不同的类型,依然是两个独立的成员,冲突依然存在。
怎么解决变量的歧义?
很简单,明确指定变量的归属即可:
System.out.println(B.a); // 输出9 System.out.println(A.a); // 输出10
内容的提问来源于stack exchange,提问作者Arun Sudhakaran
相关产品推荐
相关产品推荐

