You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java父类引用调用子类变量和方法返回不同结果的原因

为什么父类引用访问成员变量和调用重写方法结果不一致

这个差异本质是Java对成员变量和实例方法采用了完全不同的绑定规则,和多态的生效范围直接相关:

  • 成员变量不支持多态,访问时走静态绑定
    子类声明和父类同名的成员变量时,不会覆盖父类的同名字段,只会发生字段隐藏:一个子类实例的内存中,会同时存在父类定义的x和子类自己定义的x两个独立的变量,互不干扰。
    直接通过.访问成员变量时,访问哪个字段完全由引用的声明类型决定,和引用实际指向的对象类型无关。你的代码中myPig、myDog的声明类型都是Animal,所以直接访问.x时,永远取的是Animal类中定义的x=10。

  • 实例方法支持运行时多态,调用时走动态绑定
    子类重写父类的实例方法时,会发生方法覆盖:方法调用的目标在程序运行时才确定,依据是引用指向的实际对象类型,和引用的声明类型无关。
    当你调用myPig.getX()时,JVM识别到myPig实际指向的是Pig类实例,就会执行Pig类中重写的getX()方法,这个方法返回的是Pig类自己定义的x=20;同理myDog.getX()会执行Dog类的重写方法,返回x=30。

补充验证:如果你把Pig类中的getX()方法删掉,再调用myPig.getX()就会返回10——此时调用的是从Animal继承来的getX()方法,该方法作用域内访问的x是父类Animal中定义的字段。
如果要在子类方法中访问被隐藏的父类同名字段,可以使用super.x语法。

测试代码

class Animal {
    
  int x = 10;
  
  public int getX() {
     return x;
  }
  
  public void animalSound() {
    System.out.println("The animal makes a sound");
  }
}

class Pig extends Animal {

  int x = 20;
  
  public int getX() {
     return x;
  }
  
  public void animalSound() {
    System.out.println("The pig says: wee wee");
  }
}

class Dog extends Animal {

  int x = 30;
  
  public int getX() {
     return x;
  }
  
  public void animalSound() {
    System.out.println("The dog says: bow wow");
  }
}

class Main {
  public static void main(String[] args) {
    Animal myAnimal = new Animal();
    Animal myPig = new Pig();
    Animal myDog = new Dog();
        
    myAnimal.animalSound();
    System.out.println(myAnimal.getX());
    System.out.println(myAnimal.x);
    
    myPig.animalSound();
    System.out.println(myPig.getX());
    System.out.println(myPig.x);
    
    myDog.animalSound();
    System.out.println(myDog.getX());
    System.out.println(myDog.x);
}
}

运行输出

The animal makes a sound
10
10
The pig says: wee wee
20
10
The dog says: bow wow
30
10

内容的提问来源于stack exchange,提问作者user2755407

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:06:10