Java子类变量值访问问题:父类引用指向子类实例时如何获取正确值
问题分析与解决方案
首先得明确:你遇到的是Java里**字段隐藏(Field Hiding)**的问题——子类的corners并没有重写父类的同名字段,而是把它"藏"起来了。Java的字段不支持多态,当你用父类类型的引用d访问字段时,编译器只会根据引用的静态类型(也就是Shape)来查找字段,所以拿到的是父类的0。
不过完全可以在不改变d的类型的情况下拿到子类的3,有两种常用方案:
方案1:用Getter方法(最推荐,符合面向对象规范)
这是最标准的做法,利用Java方法的多态特性来实现。给父类添加一个获取字段的方法,子类重写它:
public class Testclass { public static void main(String[] args) { Shape d = new Triangle(); System.out.println(d.getCorners()); // 输出3 } } class Shape{ int corners = 0; // 父类定义获取方法 public int getCorners() { return corners; } } class Triangle extends Shape{ int corners = 3; // 子类重写方法,返回自己的字段值 @Override public int getCorners() { return corners; } }
原理:方法是支持多态的,当父类引用调用getCorners()时,JVM会根据对象的实际类型(Triangle)来执行子类的重写方法,自然就能拿到3。而且这种方式还遵循了封装原则,避免直接暴露字段。
方案2:强制类型转换(应急方案,不推荐)
如果没办法修改父类和子类的代码,那可以把d强制转换成Triangle类型后再访问字段:
public class Testclass { public static void main(String[] args) { Shape d = new Triangle(); // 先判断类型,避免ClassCastException if (d instanceof Triangle) { System.out.println(((Triangle) d).corners); // 输出3 } } }
注意:一定要先通过instanceof判断类型,不然如果d实际指向的不是Triangle实例,会抛出ClassCastException异常。这种方式虽然能解决问题,但破坏了封装,也不够灵活,只适合临时应急。
总结:优先用第一种Getter方法的方案,既安全又符合面向对象的设计思想;第二种方案只在无法修改类结构时使用。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

