Java中同名静态变量行为及类型转换后变量取值疑问
为什么Java中同名静态变量会出现不同值?
核心原因:静态变量的「隐藏」而非「继承」
Java里静态变量属于类本身,不会被子类继承。如果子类声明了和父类同名的静态变量,这属于「隐藏(hide)」父类的静态变量——两个变量是完全独立的,分别属于父类和子类各自的类空间,不存在指向同一变量的情况。
结合你的代码逐步分析
先明确各静态变量的归属:
A.s:属于A类的静态变量C.s:C类自己声明的静态变量,和A.s完全独立,隐藏了父类A的s- B类没有自己的
s,所以B中访问的s都是A.s - D类没有自己的
s,所以D中访问的s都是C.s
接下来看代码执行过程中静态变量的变化:
创建
B b = new B(7)- 调用父类A的构造器:
A(7)将A.s设为7+1=8,同时输出A constructor called! String s is:8 - B的构造器把自己的实例变量
o设为7,b.toString()输出B2S: 7 8(这里的s是A.s)
- 调用父类A的构造器:
创建
C c = new C(5)- 先调用A的构造器:
A(5)将A.s更新为5+1=6,输出A constructor called! String s is:6 - 再执行C的构造器:把
C.s设为5-1=4,输出C constructor called! String s is:4 c.toString()输出C2S: 5 4(这里的s是C.s)
- 先调用A的构造器:
创建
D d = new D(3)- 先调用A的构造器:
A(3)将A.s更新为3+1=4,输出A constructor called! String s is:4 - 再执行C的构造器:把
C.s设为3-1=2,输出C constructor called! String s is:2 - D的构造器把自己的实例变量
o设为3,d.toString()输出D2S: 3 2(这里的s是C.s)
- 先调用A的构造器:
解答你的具体疑问
为什么
((A)b).s输出4?
静态变量的访问是由编译时的类型决定的,和运行时实例类型无关。((A)b)的编译类型是A,所以访问的是A.s——此时A.s在创建D的过程中被更新成了4,所以输出4,而不是你以为的2(2是C.s的值,和A.s完全无关)。为什么同名静态变量不是同一个?
子类C声明static int s时,并没有覆盖父类A的s,而是在自己的类空间里创建了一个全新的静态变量。这和实例方法的重写(override)完全不同:静态成员属于类,实例成员属于对象,静态成员不存在动态绑定的逻辑。
额外验证:代码中其他s的输出
b.s:编译类型是B,B没有自己的s,所以访问A.s,输出4c.s:编译类型是C,访问C.s,输出2d.s:编译类型是D,继承C的s,访问C.s,输出2
内容的提问来源于stack exchange,提问作者Amadeus
相关产品推荐
相关产品推荐

