2014-03-13 49 views
8

我已经搜索了关于堆栈溢出的后期绑定的所有类似问题,并且我会严重不同意将这个问题标记为重复的任何人。首先,我在另一个问题上找到了这个例子,但是我不明白在编译期间何时决定什么时候以及何时在运行时决定什么时我应该知道该怎么做。基本上,我的问题的症结归结为两点:Java中的后期绑定

  • 在什么这个例子必须带我到逻辑结论,一个方法是后期绑定而另一个早期绑定

  • 如何我知道什么时候决定哪些执行方法的版本在运行时决定或编译时在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

最后的静态或私有方法不会发生后期绑定。对于任何其他它确实如此。就这些。 – Pshemo

+3

给未来读者的提示:上面代码中的注释不正确! –

+1

如果我的回答很有帮助,您可以请修改意见然后 – user3163829

回答

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的实现将被发现,约束,和使用。

该变量的静态(声明)类型仅供编译器用来验证此类方法是否可访问。

相关:

6

错误在所有计数。要调用的方法是在运行时决定的,这里的每种情况都是基于对象的运行时类型。在编译时做出的唯一决定是调用final,private或static方法,或者在一组重载方法中进行选择(如果重载方法不是最终的,私有的或静态的,这仍然会导致运行时选择。)

0

考虑语句

A ref; //reference of A 
    ref = new B();//Object of B 
     ref.f2(); 

这里裁判是的class A参考并且其具有的class B F2(对象的地址)是overridden方法。

当编译器检测到这样的语句时,它不会将函数调用与任何定义绑定。它只验证呼叫。

这些调用的绑定留给运行时环境。在程序运行时,系统识别对象的数据类型,并将函数调用与对象类提供的函数定义绑定。函数调用和函数定义之间的这种类型的绑定称为“后期绑定”或“运行时绑定”或“运行时多态性”或“动态方法分派”。

通过this question and read my answer例子也在那里给出。

0

当你在任何对象上调用一个方法时,总会记住在继承中调用方法的“最少修改版本”。这只不过是从层次结构中动态选取方法版本。

1

这里的所有答案大部分是正确的,但是关于Java中后期绑定有一个关键点缺失。
如果我们通过后期绑定的定义,Java不会执行“通过本书”后期绑定。 其书本定义表单中的后期绑定意味着编译器不应执行参数检查,对方法调用不进行类型检查,并且应该将其全部留给运行时 - 因为编译器可能无法访问方法实现代码(例如在COM编程中)。 然而,Java在编译时确实会验证,即使是在一个多态的场景中,被调用的方法和方法签名确实存在于表达式的类型层次结构的某处,从而使该方法有效。因此,例如,可以说,我请裁判的方法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后期绑定,因此存在混淆。