Java 中的后期绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22391915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Late Binding in Java
提问by user3163829
I have searched through all the similar questions on late binding on stack overflow, and I would severely disagree with anyone who marks this question as a duplicate. First off, i found this example on another question, but I do not understand how I am supposed to know when something is decided during compile time and when something is decided during run time. Basically, the crux of my question boils down to two things:
我已经搜索了所有关于堆栈溢出延迟绑定的类似问题,我非常不同意将这个问题标记为重复的任何人。首先,我在另一个问题上找到了这个例子,但我不明白我应该如何知道什么时候在编译时决定什么,什么时候在运行时决定什么。基本上,我的问题的关键归结为两件事:
What in this example mustbring me to the logical conclusion that one method is late binding and another is early binding
How do I know when the decision about which version of a method to execute is decided during run-time or compile time in Java
在这个例子中,我必须得出一个合乎逻辑的结论,即一种方法是后期绑定,另一种是早期绑定
我如何知道在 Java 中的运行时或编译时决定执行哪个版本的方法的决定
Code:
代码:
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(); }
}
回答by Sotirios Delimanolis
Java uses late binding for all non-final, non-private instance methods. This is how polymorphism is implemented. All of the calls you commented on are determined at run time.
Java 对所有非最终的、非私有的实例方法使用后期绑定。这就是多态的实现方式。您评论的所有调用都是在运行时确定的。
In
在
A a=new A();
a.foo();
a
is referencing an A
object so A
's implementation will be found, bound and used.
a
正在引用一个A
对象,因此A
将找到、绑定和使用 的实现。
In
在
B b=new B();
b.foo();
b
is referencing a B
object so B
's implementation will be found, bound, and used.
b
正在引用一个B
对象,因此B
将找到、绑定和使用 的实现。
In
在
ref=b;
ref.foo();
ref
is referencing a B
object so B
's implementation will be found, bound, and used.
ref
正在引用一个B
对象,因此B
将找到、绑定和使用 的实现。
The static (declared) type of the variable is only used by the compiler to verify that such a method is accessible on that type.
变量的静态(声明)类型仅由编译器用于验证该方法是否可在该类型上访问。
Related:
有关的:
回答by Ernest Friedman-Hill
Wrong on all counts. The method to be called is decided at runtime, in every case here, based on the runtime type of the object. The only decisions made at compile time are for calls to final, private, or static methods, or choices among a set of overloaded methods (which could still lead to runtime choices if the overloaded methods are not final, private, or static.)
各方面都错了。要调用的方法是在运行时决定的,这里的每种情况都基于对象的运行时类型。在编译时做出的唯一决定是调用 final、private 或 static 方法,或者在一组重载方法中进行选择(如果重载方法不是 final、private 或 static,这仍然可能导致运行时选择。)
回答by Ashish
Consider the statement
考虑语句
A ref; //reference of A
ref = new B();//Object of B
ref.f2();
Here ref is a reference of class A
and it has address of object of class B
f2() is a overridden
method.
这里 ref 是一个引用,class A
它有class B
f2()对象的地址是一个overridden
方法。
When compiler detects such a statement then it doesn't bind the function call with any definition. It only validates the call.
当编译器检测到这样的语句时,它不会将函数调用与任何定义绑定。它只验证调用。
Binding of such calls is left for the runtime environment. At program runtime system identifies the datatype of the object and binds the function call with the function definition provided by the class of object. This type of binding between the function call and function defination is called as "late binding"or "runtime binding" or "runtime polymorphism"or "dynamic method dispatch".
此类调用的绑定留给运行时环境。在程序运行时系统识别对象的数据类型并将函数调用与对象类提供的函数定义绑定。函数调用和函数定义之间的这种类型的绑定称为“后期绑定”或“运行时绑定”或“运行时多态”或“动态方法分派”。
go through this question and read my answerexample is also given there.
通过这个问题并阅读我的答案示例也给出了。
回答by bk01
When you call a method on any object, always remember in inheritance "least modified version" of method will be called. This is nothing but dynamically picking the method version from the hierarchy.
当您在任何对象上调用方法时,请始终记住在继承中将调用方法的“最少修改版本”。这只不过是从层次结构中动态选择方法版本。
回答by programmerravi
All the answers here are mostly correct, but there is one key point missing regarding late binding in Java.
Java does not perform "by the book" late binding if we go by the definition of late binding.
Late binding in its book definition form means that the compiler should perform no argument checks, no type checks on a method call and should leave it all to the runtime - because possibly the compiler does not have access to the method implementation code (for example in COM programming).
Java however at compile time does verify, even in a polymorphic scenario, that the method being called and the method signature does exist somewhere in the type hierarchy of the expression that qualifies the method. So for example, lets say I call a method foo1 on ref that does not exist in either A or B:
这里的所有答案大部分都是正确的,但是关于 Java 中的后期绑定,缺少一个关键点。
如果我们遵循后期绑定的定义,Java 不会执行“按书本”后期绑定。其书本定义形式的后期绑定意味着编译器不应对方法调用执行参数检查、类型检查,而应将其全部交给运行时——因为编译器可能无法访问方法实现代码(例如在COM 编程)。然而,Java 在编译时会验证,即使在多态场景中,被调用的方法和方法签名确实存在于限定该方法的表达式的类型层次结构中的某处。例如,假设我在 A 或 B 中都不存在的 ref 上调用了一个方法 foo1:
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.
In a purelate binding scenario, the determination of whether the method foo1() exists or not with the right number of arguments is made purely at runtime.
However in Java, there is some level of checking done at compile time, to ensure that the method with the right number of arguments does exist somewhere in the type hierarchy.
The only time that I think Java does perform purelate binding is if one uses reflection to call a method.
What Java does is better termed as dynamic dispatch rather than late binding, but everyone calls it late binding in Java and hence there is confusion.
在纯粹的后期绑定场景中,纯粹在运行时确定方法 foo1() 是否存在并带有正确数量的参数。但是,在 Java 中,在编译时会进行某种程度的检查,以确保具有正确数量的参数的方法确实存在于类型层次结构中的某处。
我认为 Java 执行纯后期绑定的唯一一次是使用反射来调用方法。Java 所做的最好称为动态调度而不是后期绑定,但在 Java 中每个人都称其为后期绑定,因此存在混淆。