父类属性覆盖子类属性问题:如何让方法输出子类属性值?
解决Java子类属性被父类同名属性覆盖的问题
这是个很典型的Java成员变量隐藏问题,我来给你拆解清楚并提供可行的解决方案:
问题根源
Java的成员变量不支持多态,当你在子类B中重新定义int cost = 10时,这并不是重写(override)父类的属性,而是**隐藏(hiding)**了父类的同名属性。
在method4A方法中,参数a的编译时类型是A,所以直接访问a.cost时,JVM会直接取父类A中cost的值(默认初始化的0),而不会去看运行时实际的子类B的cost属性。
解决方案
方案1:使用Getter方法(推荐,符合面向对象设计)
这是最规范的做法,通过方法的多态性来实现正确的属性访问:
class A { int cost; // 父类添加Getter方法 public int getCost() { return cost; } } class B extends A { int cost = 10; // 子类重写Getter方法,返回自己的cost值 @Override public int getCost() { return cost; } } class Test { public static void main(String[] args) { B b = new B(); method4A(b); } static void method4A(A a) { // 调用Getter方法而非直接访问属性 System.out.println(a.getCost()); // 输出10 } }
因为Java的方法支持多态,调用a.getCost()时,JVM会根据实例的运行时类型(B)执行子类重写的方法,从而返回子类的cost值。
方案2:子类不重新定义属性,直接赋值父类属性
如果不需要子类单独拥有一个cost属性,完全可以直接复用父类的属性,在子类构造器中赋值:
class A { int cost; } class B extends A { // 不在子类重新定义cost,直接在构造器中给父类属性赋值 public B() { this.cost = 10; } } class Test { public static void main(String[] args) { B b = new B(); method4A(b); } static void method4A(A a) { System.out.println(a.cost); // 输出10 } }
这样子类实例中只有一个继承自父类的cost属性,访问时自然就是赋值后的10。
方案3:强制类型转换(不推荐,仅临时场景使用)
如果一定要保留子类的独立cost属性,可以在方法中把父类引用转为子类类型,但要注意类型安全:
class A { int cost; } class B extends A { int cost = 10; } class Test { public static void main(String[] args) { B b = new B(); method4A(b); } static void method4A(A a) { // 先判断类型,避免ClassCastException if (a instanceof B) { System.out.println(((B)a).cost); // 输出10 } else { System.out.println(a.cost); } } }
这种方式会破坏封装性,且如果传入的不是B类型的实例会报错,只适合临时调试或特殊场景。
总结
优先选择方案1,它既符合面向对象的封装原则,又利用了方法多态性保证代码的健壮性和可维护性。
内容的提问来源于stack exchange,提问作者nestor556
相关产品推荐
相关产品推荐

