接口隐式静态final属性的覆盖疑问:为何运行结果为ABCI?
接口静态属性为何呈现类似覆盖的表现?
代码示例
interface I{ String s="I"; } class A implements I{ String s="A"; } class B extends A{ String s="B"; } class Demo extends B{ String s="C"; void print(){ System.out.print(((A)this).s+((B)this).s+((Demo)this).s+((I)this).s); } public static void main(String args[]){ new Demo().print(); } }
运行结果
Result - ABCI
问题
从运行结果来看,接口I中的属性s似乎被实现类及子类覆盖,但接口的属性默认是隐式final和static的,为何会出现这种类似覆盖的表现?
解答
这不是方法重写那样的覆盖(Override),而是成员的隐藏(Hiding),二者本质完全不同:
- 接口里的
s是public static final的,它属于接口I本身,和任何类的实例都无关,是类级别的静态常量。 - 实现类A、子类B和Demo里声明的
s,都是各自类的实例成员变量,和接口I的s只是名字相同,完全是不同的变量。 - 代码里的强制类型转换,决定了编译时访问的变量归属:
((A)this).s:访问A类的实例变量s((B)this).s:访问B类的实例变量s((Demo)this).s:访问Demo类的实例变量s((I)this).s:看起来是通过实例访问,实际上编译器会自动转换成I.s——因为接口的静态成员只能属于接口本身,强制转换只是让编译器允许这个写法,最终取的还是接口的静态常量值。
简单说,同名变量只是名字冲突,各自属于不同的类型,不存在“覆盖”。覆盖只针对实例方法,而静态成员、实例变量的同名情况都是隐藏,访问时看的是编译时的类型,而非运行时类型。
内容的提问来源于stack exchange,提问作者Chinthaka Prasad Wijerathna
相关产品推荐
相关产品推荐

