核心Java动态绑定
请告诉我们获得产量的原因 根据我的说法,使用b.getx()我们将得到b的对象的引用id,并且核心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().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
)。。。