Java动态绑定混淆

Java动态绑定混淆,java,dynamic,binding,Java,Dynamic,Binding,我不明白为什么2。方法(C)返回C4。不是两个声明为超级类型。这难道不意味着它只能访问超级方法吗?我以为它会回来。至少这是我从@stvcisco在前面一个类似问题中给我的答案中推断出来的。 我是否误解了他的答案?正在调用的实例方法取决于实例的运行时类型 在Super-two=new-Sub()中,运行时类型为Sub(即使编译时类型为Super)。因此two.methodC(three)调用Sub的methodC(Sub-arg) 编译时类型确定编译器将接受的可用方法签名。由于Super包含一个签

我不明白为什么2。方法(C)返回C4。不是两个声明为超级类型。这难道不意味着它只能访问超级方法吗?我以为它会回来。至少这是我从@stvcisco在前面一个类似问题中给我的答案中推断出来的。
我是否误解了他的答案?

正在调用的实例方法取决于实例的运行时类型

Super-two=new-Sub()中
,运行时类型为
Sub
(即使编译时类型为
Super
)。因此
two.methodC(three)
调用
Sub
methodC(Sub-arg)

编译时类型确定编译器将接受的可用方法签名。由于
Super
包含一个签名与调用
two.methodC(three)
匹配的方法,因此此代码可以通过编译。但是,调用的实际方法仅在运行时根据运行时类型
two
确定

不是两个声明为超级类型

是的

这难道不意味着它只能访问超级方法吗

不,不是这个意思

发生的情况如下:

在编译时,编译器检查Super中是否有一个方法可以处理
methocC(Sub)
。实际上有两个<代码>方法C(超级)和
方法C(子)
。编译器在运行时选择要绑定的最特定的签名。这是
methodC(Sub)
,因为
Sub
Super
的一个子类


在运行时,VM在最具体的类中查找
methodC(Sub)
。这是
Sub
,因为这里定义了一个带有签名的方法
methodC(Sub)
,所以这是绑定的。

这是因为您覆盖了两个函数
methodC(Super)、methodC(Sub)
。和
Super two=new Sub()
,这称为多态性。这意味着它将指向局部变量“new Sub()”和
类Sub
中的函数,尽管您将其命名为
类Super
。所有这一切都是自动完成的。如果您在
类Super
中有一个方法
methodC(Super),methodC(Sub)
,但是
methodB(Super),methodB(Sub)
中的
类Sub
。相同的操作'Super-two=new-Sub();方法c(三)
将返回“C2”。此外,你问的问题很常见。你需要编写更多的代码来理解它。最好编写一个包含更多类的项目。例如
Class Super;类Sub1扩展了Super;类别Sub2<当然,您也可以使用
接口`

案例1)“two”是一种超类,但它包含子类对象。所以,当您调用某个在超级类和子类中定义的方法时,它会调用子类方法,因为子类重写了该方法。如果在子类中找不到这些方法,则调用超类方法

案例2)当您从super和Sub-class中删除方法“methodC(Sub-arg)”时,它将调用子类方法“methodC(super-arg)”,如果未找到,则调用super-class方法

将子类对象指定给超级类对象时,它将 调用第一个子类方法,因为子类重写了超类 方法


在理解动态绑定和静态绑定的概念时,我认为最重要的是,很多时候,我们认为这两种类型的绑定都不能在程序的范围内发生——这两种绑定是相互排斥的,这是不正确的。只是这两种情况发生在程序执行的不同阶段,如果发现任何歧义,就会抛出一个错误。例如,在您的情况下:

public class BindingQuestion {
    public static void main (String[] args){
    Super one = new Super();
    Super two = new Sub();
    Sub three = new Sub();
    two.methodC(three)
    }
}
在编译时----------------

在编译程序时,java编译器将遍历每个可执行代码。说到

public class BindingQuestion {
    public static void main (String[] args){
        Super one = new Super();
        Super two = new Sub();
        Sub three = new Sub();
        two.methodC(three)
    }
}
它将首先检查带有此签名的methodC(三)是否在SUPER类型的类中可用。为什么是超级?因为java中的对象是通过引用访问的。执行此操作时:

two.methodC(three)
这意味着,对于Super类型的引用2,您指向SUB的对象,这很好。为什么?因为在java中,子类除了由其超类植入的属性外,总是有一些额外的属性。因此,从上面的代码来看,SUB的所有属性都可以很好地工作——它们很容易被SUPER类型的引用变量访问

因此,编译器检查方法 在编译器通过程序执行并且没有发现任何与methodC(三)匹配的引用类型方面的歧义之后,是否在超类中存在

根据您提供的继承结构,是否有一个名为methodC的方法是超类。答案是肯定的!它确实存在。现在,参数匹配吗?换句话说,签名是否匹配?答案是肯定的。因为在SUPER中,公共void methodC(Subarg)中需要签名。你猜怎么着?第三,是SUB类型。所以编译器将通过这一行而不会产生任何错误

即将开始运行时间 您必须记住,对象和仅在运行时调用。方法和签名类型的检查是在编译时完成的

现在,Java运行时实例在调用对象2时,意识到对象2实际上是子类,并调用子类中的方法。 希望这有帮助

public class BindingQuestion {
    public static void main (String[] args){
        Super one = new Super();
        Super two = new Sub();
        Sub three = new Sub();
        two.methodC(three)
    }
}
two.methodC(three)
Super two = new Sub();