指向基类的动态多态性引用

时间:2014-03-02 05:09:55

标签: java dynamic

我需要澄清Java的动态多态性。

class Foo {
  int a=3;
  public void display() {
    System.out.println(" in foo "+a);
  }
}

class Bar extends Foo {
  int a=8;
  public void display() {
    System.out.println(" in boo "+a);
  }
}

public class Tester {
 public static void main(String[]args) {
  Foo f = new Bar();
  f.display();
  System.out.println(f.a);
 }
}

这里,当我使用基类引用创建子类对象时,在调用方法f.display()时,它将输出作为in boo 8。这是因为动态多态,它在运行时检查对象类型以调用方法。

现在打印f.a时打印3,因为在java中无法覆盖变量,这称为隐藏。这就是为什么它显示基本变量值而不是子变量值。

现在我的问题是f是基类的引用,它指向子类对象。那么f.a如何指向基本变量。 幕后发生了什么?引用如何指向基类?

(我知道规则,但我想知道如何/为什么?)

3 个答案:

答案 0 :(得分:4)

我不知道这是否超出了你的学习范围,但现在就是这样。编译代码时,编译器会生成JVM执行的字节代码。

Foo.a中字段f.a的引用
System.out.println(f.a);

编译为

getfield      #6                  // Field Foo.a:I

其中getfielda bytecode instruction

  

获取对象objectref的字段值,其中字段为   由常量池索引中的字段引用标识(index1 <&lt; 8   + index2)

和常量池

Constant pool:
   // [...]
   #6 = Fieldref           #20.#24        //  Foo.a:I
   // [...]

因此,字节代码引用类Foo中的字段,即变量的声明类型,而不是实例的运行时类类型。


您可以使用以下命令查看生成的字节代码

javap -c -v YourClass

答案 1 :(得分:4)

这是因为您在问题中已经说明了这一点:

  

变量无法在Java中重写

因此,引用f.a在编译时静态解析,它将编译器带到Foo.a,即3

答案 2 :(得分:0)

因为变量无法被覆盖,所以你从基类中提供了它的

的引用
print f.a = 3 

如果你这样声明

Bar f = new Bar();

现在您打印f.a的值,它会为您提供8