Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
核心Java动态绑定_Java_Core - Fatal编程技术网

核心Java动态绑定

核心Java动态绑定,java,core,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();

请告诉我们获得产量的原因

根据我的说法,使用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);
  }
}
字段访问(与方法调用不同)不受运行时动态调度的约束,它们完全基于编译时类型进行解析

变量
b
是编译时类型
Base
,因此
b.getx()
也是编译时类型
Base
,因此
b.getx().x
将被编译到Base的
x
字段的访问中,而不是子字段。通过查看
main
方法的
javap
输出,可以确认这一点:

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
publicstaticvoidmain(java.lang.String[]);
代码:
0:新#3//班童
3:dup
4:特别是#4//方法“”:()V
7:astore_1
8:getstatic#5//字段java/lang/System.out:Ljava/io/PrintStream;
11:aload_1
12:invokevirtual#6//方法库getx:()LBase;
15:getfield#7//野战基地
18:invokevirtual#8//方法java/io/PrintStream.println:(I)V
21:返回

您可以看到,
b.getx().x
被编译成
Base.x
getfield
指令。

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

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

示例:

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");
   }
}
Base b=new Child()是在运行时解析的,通过动态绑定(运行时多态性)的规则,所有与之相关的方法都应该在运行时绑定,所以

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

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

这是否意味着数据成员在编译时被绑定?因为如果我们从这两个类中删除int x并使用System.out.println(b.getx());它调用子类对象。@ShardaPrasadJaiswal是的,
b.getx()
的运行时类型将是
child
,但这不会影响仅基于点左侧表达式的编译时类型的字段访问
a.x
。想象一下,如果
Base.x
Child.x
属于不同的类型(例如一个
int
和一个
String
)。。。