静态绑定在编译时发生,动态绑定在运行时发生。
静态绑定 负责选择应执行的方法的 签名 (名称和参数类型)。它用
- __方法 名称
- 带有参数的变量类型(编译器不假定运行时实际的对象变量将保留,他选择了能够处理所有可能情况的签名)。
编译器会选择签名 从该方法被调用变量的类型 ,所以
Object o = "abc";会 不会
让你调用
o.substring(1,2);,因为编译器将无法找到
substring(int,int)在签名
Object类(这是类型
o上的变量
substring被调用的方法)。
- 动态绑定* 负责在编译时 _查找和调用 _通过静态绑定选择的方法的 _ 代码* 。它将尝试查找变量持有的 _实际实例 类型的方法代码。换句话说,如果有的
Animal a = new Cat(); a.makeSound();
话,可以期望得到结果,"Mew"
因为在运行时JVM将搜索并调用makeSound
从Cat
类开始的代码。如果在该类中未提供实现,则JVM将在祖先中搜索它,直到找到从其继承的继承。
我对示例中的类和变量进行了重命名,以期使其更具可读性:
class A { public void print(A a) { System.out.println("A.print(A)"); }}class B extends A { public void print(A a) { System.out.println("B.print(A)"); } public void print(B b) { System.out.println("B.print(B)"); }}class C extends B { public void print(A a) { System.out.println("C.print(A)"); } public void print(B b) { System.out.println("C.print(B)"); } public void print(C c) { System.out.println("C.print(C)"); }}class OverloadingDemo { public static void main (String [] args) { A ab = new B(); A ac = new C(); B bb = new B(); B bc = new C(); bc.print(new A()); bc.print(new C()); bc.print(new B()); ab.print(new C()); ac.print(new C()); ac.print(new B()); bb.print(new C()); }}
(变量命名->
X持有类型的实例的类型的变量
Y被命名为
xy)。
所以,当我们执行
bc.print(new A());
- 静态绑定将尝试找到可处理type实例的 类 中 可用的 最佳
print
方法签名。在这种情况下将是。B
A``print(A)
- 之后,动态绑定将在类中搜索此方法的 代码
C
(因为这是bc
变量持有的实例的类型),这意味着我们将看到C.print(A)
。
同样的情况
bc.print(new C());
- 静态绑定将尝试为类中可用
print
的C
参数找到最佳方法B
,这C
是print(B)
因为(因为那里没有print(C)
,并且B是最接近的超类型)。 - 所以现在动态绑定知道要在
C
类中查找哪种方法(因为这是bc
保存的实例)。
因此它将调用
C.print(B)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)