核心Java动态绑定

时间:2013-05-15 15:30:52

标签: java core

请告诉我们输出的原因。

按照我的说法,使用b.getx()我们将获得B对象的引用ID,b.getx().x应该得到10的值,但是当我运行这个程序时,输出为5。

class Base {
  int x = 5;
  public Base getx() {
    return new Base();
  }
}

class Child extends Base {
  int x = 10;
  public Child getx() {
    return new Child();
  }

  public static void main(String ...s) {
    Base b = new Child();
    System.out.println(b.getx().x);
  }
}

4 个答案:

答案 0 :(得分:8)

字段访问(与方法调用不同)不受运行时动态调度的影响,它们仅基于编译时类型进行解析。

变量b属于编译时类型Base,因此b.getx()也是编译时类型Base,因此b.getx().x将是编译成Base的x字段的访问权限,而不是Child的。通过查看javap方法main的输出来确认:

public static void main(java.lang.String[]);
  Code:
   0:   new #3; //class Child
   3:   dup
   4:   invokespecial   #4; //Method "<init>":()V
   7:   astore_1
   8:   getstatic   #5; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_1
   12:  invokevirtual   #6; //Method Base.getx:()LBase;
   15:  getfield    #7; //Field Base.x:I
   18:  invokevirtual   #8; //Method java/io/PrintStream.println:(I)V
   21:  return

您可以看到b.getx().x专门编译为getfield Base.x指令。

答案 1 :(得分:1)

动态绑定基本上意味着实际调用的方法实现是在运行时确定的,而不是在编译时确定的。这就是为什么它被称为动态绑定 - 因为将在运行时选择将运行的方法。动态绑定也称为后期绑定。

答案 2 :(得分:1)

Base b = new Child();在运行时解析,并且通过动态绑定规则(运行时多态性),所有与此相关的方法都应该在运行时绑定,所以......

public Base getx() {
    return new Base();
  }

这些行返回基类的新实例,你只是在该实例上调用了变量。

答案 3 :(得分:0)

动态绑定是在运行时查看声明的运行时时间过程。它也称为后期绑定,其中对重写方法的调用在运行时而不是编译时解析。 在面向对象的系统方法中,覆盖(动态多态)在运行时完成。当用一种方法覆盖另一种方法时,两种方法的签名必须相同。

示例:

class Animal{

  public void eat(){
      System.out.println("Animals voice");
   }

public void go(){
      System.out.println("Animals can walk");
   }

}

class Dog extends Animal{

   public void go(){
      System.out.println("Dogs can walk and run");
   }
   public void eat(){
      System.out.println("Dogs can eat a wide range of foods");
   }
}