Java动态(后期)绑定和overloading 向上转型

举报
ShaderJoy 发表于 2021/11/18 23:34:12 2021/11/18
【摘要】 动态绑定:意味着 目前正在调用的方法正是最适用于要操作对象的那个方法。然而它并不意味着对所有的参数都执行最佳匹配。 在Java中,一个方法的参数在编译阶段常被 静态地绑定。 一个例子:动态绑定和静态重载 class Base{ public void foo(Base x){ Syst...

动态绑定:意味着 目前正在调用的方法正是最适用于要操作对象的那个方法。然而它并不意味着对所有的参数都执行最佳匹配。

静态地绑定

一个例子:动态绑定和静态重载


  
  1. class Base{
  2. public void foo(Base x){
  3. System.out.println("Base.Base");
  4. }
  5. public void foo(Derived x){
  6. System.out.println("Base.Derived");
  7. }
  8. }

   
  1. class Derived extends Base{
  2. public void foo(Base x){
  3. System.out.println("Derived.Base");
  4. }
  5. public void foo(Derived x){
  6. System.out.println("Derived.Derived");
  7. }
  8. }


   
  1. class Main{
  2. public static void whichFoo(Base arg1, Base arg2){
  3. arg1.foo(arg2);
  4. }
  5. public static void main(String[] args)}{
  6. Base b = new Base();
  7. Derived d = new Derived();
  8. whichFoo(b,b);
  9. whichFoo(b,d);
  10. whichFoo(d,b);
  11. whichFoo(d,d);
  12. }
  13. }

分析:

编译阶段 whichFoo方法中 arg2的类型是Base


public void foo(Base x)
 

惟一的问题

arg1的运行时类型

总结:

精确使用的方法是编译器绑定,在编译阶段,最佳方法名依赖于参数的静态和控制引用的静态类型所适合的方法。在这一点上,设置方法的名称,这一步叫静态重载
决定方法是哪一个类的版本,这通过由虚拟机推断出这个对象的运行时类型来完成,一旦知道运行时类型,虚拟机就唤起继承机制,寻找方法的最终版本。这叫做动态绑定

由此理解方法的覆盖和重载。重载函数的实际调用版本由编译器绑定决定,而覆盖函数的实际调用版本由动态绑定决定。

看一个例子:有歧义的重载


  
  1. class Point { int x, y; }
  2. class ColoredPoint extends Point { int color; }
  3. class Test {
  4. static void test(ColoredPoint p, Point q) {
  5. System.out.println("(ColoredPoint, Point)");
  6. }
  7. static void test(Point p, ColoredPoint q) {
  8. System.out.println("(Point, ColoredPoint)");
  9. }
  10. public static void main(String[] args) {
  11. ColoredPoint cp = new ColoredPoint();
  12. test(cp, cp); // compile-time error
  13. }
  14. }

分析:

这个例子会在编译时提示一个错误,错误在于声明的两个test方法在编译器看起来都是可行的,彼此之间都不具备进一步说服编译器调用自己的理由,所以编译器就为难的抛出一个存在调用歧义的错误。
如果我们增加一个test的重载定义如下: 


  
  1. static void test(ColoredPoint p, ColoredPoint q) {
  2. System.out.println("(ColoredPoint, ColoredPoint)");
  3. }





问题:方法的参数是父类对象,传入子类对象是否可行

引出的一连串的问题:


向上转型



程序绑定的概念:



静态绑定:


java当中的方法只有final,static,private和构造方法是前期绑定

动态绑定:





动态绑定的过程:







关于绑定相关的总结:

java属于后期绑定 几 乎 特殊 特别说明 一、 二、 C++则不同,必须明确的声明某个方法具备后期绑定


向上转型
方法 final,static,private和构造方法

其具体过程细节如下:


“重载解析”
动态绑定

上面是理论,下面看几个示例(示例来自网络):  


  
  1. public class Father {
  2.   public void method() {
  3.     System.out.println("父类方法,对象类型:" + this.getClass());
  4.   }
  5. }
  6.   
  7. public class Son extends Father {
  8.   public static void main(String[] args) {
  9.     Father sample = new Son();//向上转型
  10.     sample.method();
  11.   }
  12. }
首先 但是 向上转型


  
  1. public class Son extends Father {
  2.   public void method() {
  3.     System.out.println("子类方法,对象类型:" + this.getClass());
  4.   }
  5.   
  6.   public static void main(String[] args) {
  7.     Father sample = new Son();//向上转型
  8.     sample.method();
  9.   }
  10. }

重写



在处理java类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。 对象的方法可以找到子类,而对象的属性还是父类的属性



  
  1. public class Father {
  2.   protected String name="父亲属性";
  3.   
  4.   public void method() {
  5.     System.out.println("父类方法,对象类型:" + this.getClass());
  6.   }
  7. }
  8.   
  9. public class Son extends Father {
  10.   protected String name="儿子属性";
  11.   
  12.   public void method() {
  13.     System.out.println("子类方法,对象类型:" + this.getClass());
  14.   }
  15.   
  16.   public static void main(String[] args) {
  17.     Father sample = new Son();//向上转型
  18.     System.out.println("调用的成员:"+sample.name);
  19.   }
  20. }



运行时(动态)绑定针对的范畴只是对象的方法





  
  1. public class Father {
  2.   protected String name = "父亲属性";
  3.   public String getName() {
  4.     return name;
  5.   }
  6.   public void method() {
  7.     System.out.println("父类方法,对象类型:" + this.getClass());
  8.   }
  9. }
  10.   
  11. public class Son extends Father {
  12.   protected String name="儿子属性";
  13.   
  14.   public String getName() {
  15.     return name;
  16.   }
  17.   
  18.   public void method() {
  19.     System.out.println("子类方法,对象类型:" + this.getClass());
  20.   }
  21.   
  22.   public static void main(String[] args) {
  23.     Father sample = new Son();//向上转型
  24.     System.out.println("调用的成员:"+sample.getName());
  25.   }
  26. }


转载自:http://www.cnblogs.com/yyyyy5101/archive/2011/08/02/2125324.html

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/13685467

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。