`
hongjn
  • 浏览: 55271 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

java动态绑定

 
阅读更多

 

对象方法的执行过程:
1).编译器查看对象的声明类型和方法名。假设调用x.f(param),对象x中可能会存在多个f方法,它们有不同的参数类型,比如f(int), f(String), f(double)等,编译器会列举x类中所有名为f的方法和其超类中访问属性为public且名为f的方法。
  经过上述过程,编译器获得所有可能被调用的候选方法。
2).编译器查看调用方法时提供的参数类型。如果所有名为f的方法中存在一个与提供的参数类型完全匹配,就选择该方法。这个过程被称为重载解析(overloading resolution)

注:方法的签名指的是方法名字,加上方法的参数列表。
       1)子类覆盖父类的方法,但该方法不能拥有比父类更严格的访问控制。特别是当父类方法是public时,子类一定要是public,否则编译器将认为该方法使用的是默认的访问控制修饰符,降低了访问控制权限,因此报错了。
       2)返回类型不是方法签名的一部分,在进行方法覆盖的时候,javase5之前要求返回类型要一致。但是javase5以后允许覆盖方法的返回类型为原返回类型的子类型,称之为可协变的返回类型(covariant return type)

举个例子:
public class Demo {
     public static void main(String[] args) {
          A a = new B();
         
          C c = a.display() ;
          c.display() ;
         
     }
}

class A {
     public C display() {
          System.out.println("this is from A!");
          return new C();
     }
}

class B extends A {
     public D display() {
          System.out.println("this is from B!");
          return new D() ;
     }
}

class C {
     public void display() {
          System.out.println("this is from C!!!");
     }
}

class D extends C {
     public void display() {
          System.out.println("this is from D!");
     }
}

程序的返回结果:
this is from B!
this is from D!

这其中的B和A的display方法就是具有协变的返回类型,因为B的display方法覆盖了A的display方法,然后B的display返回的结果类型是D,D是C的子类,而A的display返回结果正好是C。因此构成可协变的返回类型(covariant return type)

3)当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用所引用对象的实际类型最合适的那个类的方法。
例如:C x = new D(); // D extends C
            x.f(String);
x引用的实际类型是D,它是C的子类。如果D定义了方法f(String),就直接调用他,否则在其超类中寻找f(String),以此类推。
每次调用方法都要进行搜索,时间开销相当大。虚拟机的解决方法是,为每个类创建一个方法表(method table),列出所有方法的签名,和实际调用的方法。以后,每次调用一个方法,虚拟机只需要找这个表就可以了。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics