我已经搜索了关于堆栈溢出的后期绑定的所有类似问题,并且我会严重不同意将此问题标记为重复的任何人。首先,我在另一个问题上找到了这个例子,但是我不明白在编译期间什么时候决定什么以及什么时候在运行时确定了什么我应该知道。基本上,我的问题的关键归结为两件事:
本例中的内容必须让我得出一个逻辑结论:一个方法是后期绑定,另一个是早期绑定
如何确定在Java中运行时或编译时决定执行哪个版本的方法
代码:
class A
{
public void foo()
{
System.out.println("Class A");
}
}
class B extends A
{
public void foo()
{
System.out.println("Class B");
}
}
public class C
{
public static void main(String [] args)
{
A a=new A();
B b=new B();
A ref=null;
/*
early binding --- calls method foo() of class A and
decided at compile time
*/
a.foo();
/* early binding --- calls method foo() of class B and
decided at compile time
*/
b.foo();
/* late binding --- --- calls method foo() of class B and
decided at Run time
*/
ref=b;
ref.foo(); }
}
答案 0 :(得分:6)
所有罪名都错了。在此处,基于对象的运行时类型,在运行时决定要调用的方法。在编译时做出的唯一决定是调用final方法,私有方法或静态方法,或者在一组重载方法中进行选择(如果重载方法不是final,private或static,它仍然可以导致运行时选择。)< / p>
答案 1 :(得分:2)
Java对所有非最终的非私有实例方法使用后期绑定。这就是多态性的实现方式。您评论的所有电话都是在运行时确定的。
在
A a=new A();
a.foo();
a
引用了A
对象,因此A
的实现将被找到,绑定和使用。
在
B b=new B();
b.foo();
b
引用了B
对象,因此B
的实现将被找到,绑定和使用。
在
ref=b;
ref.foo();
ref
引用了B
对象,因此B
的实现将被找到,绑定和使用。
变量的静态(声明)类型仅供编译器用于验证此类型上是否可以访问此类方法。
相关:
答案 2 :(得分:1)
这里的所有答案大多都是正确的,但是关于Java中的后期绑定,有一个关键点缺失 如果我们按照后期绑定的定义,Java不会执行“由书”后期绑定。 其书籍定义形式中的后期绑定意味着编译器不应执行参数检查,不对方法调用进行类型检查,并且应将其全部留给运行时 - 因为编译器可能无法访问方法实现代码(例如, COM编程)。 但是,Java在编译时确实会验证,即使在多态方案中,被调用的方法和方法签名确实存在于限定方法的表达式的类型层次结构中的某处。例如,假设我在ref上调用了一个方法foo1,它在A或B中都不存在:
A ref=null;
ref=new B();
ref.foo1();
//This will not compile in Java, because java will check at compile time
//for the method foo1 in the type hierarchy of A, which is the type of the
// variable ref at compile time.
//In pure late binding, however this would pass compilation and
//throw an error at runtime.
在纯后期绑定方案中,确定方法foo1()是否存在且具有正确数量的参数是纯粹在运行时。
但是在Java中,在编译时进行了一定程度的检查,以确保具有正确数量的参数的方法确实存在于类型层次结构中的某个位置。
我认为Java执行纯后期绑定的唯一时间是使用反射来调用方法。
Java所做的最好被称为动态调度而不是后期绑定,但每个人都称之为Java后期绑定,因此存在混淆。
答案 3 :(得分:0)
考虑声明
A ref; //reference of A
ref = new B();//Object of B
ref.f2();
此处ref是class A
的引用,它的对象地址为class B
f2()是overridden
方法。
当编译器检测到这样的语句时,它不会将函数调用与任何定义绑定。它只验证通话。
此类调用的绑定留给运行时环境。在程序运行时,系统识别对象的数据类型,并使用对象类提供的函数定义绑定函数调用。函数调用和函数定义之间的这种类型的绑定称为&#34;后期绑定&#34; 或&#34;运行时绑定&#34;或&#34;运行时多态&#34; 或&#34;动态方法调度&#34;。
通过this question and read my answer示例也在那里。
答案 4 :(得分:0)
当您在任何对象上调用方法时,请始终记住在继承中将调用“最少修改版本”的方法。这只不过是从层次结构中动态选择方法版本。