`
Strive_sprint
  • 浏览: 22492 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

借助动态绑定实现向上转型

 
阅读更多

 

      首先介绍一下绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定(前期绑定)和动态绑定(后期绑定)

 

      静态绑定(前期绑定)是指在程序执行前方法已经被绑定,可以理解为程序编译期的绑定。只有final,static,private和构造方法是前期绑定,因为private方法是不能被继承的,所以和final方法有相同的效果,也可以说是用来有效的关闭动态绑定的,而static方法在编译时就分配了方法区的内存,所以都是静态绑定。也许还不太好理解,但是理解了动态绑定也就理解了静态绑定;

      动态绑定(后期绑定)即运行时绑定,指在运行期间判断对象的类型,并调用适当的方法。也就是说,编译器不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。

 

      动态绑定的过程如下:

      1.编译器检查对象的声明类型和方法名,然后的实际类型的方法表。加入A类中对象a调用fun(obj)方法,那么编译器会列出所有A类中fun()方法,和A类父类中所有fun()方法以及A父类的父类的所有方法以及更上层的。

      2.编译器检查方法调用中提供的参数类型,如果在所有fun()方法中有一个参数类型和调用提供的参数类型最为匹配,那么就调用这个方法。这个过程叫做“重载解析”。

      3.当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同a所指向的对象的实际类型相匹配的方法,如果A类中有合适的方法则调用,否则在A的父类中找以及更上层。

 

      光说不练嘴把式,废话说了这么多,咱也来点实际的! Look:

 

父类

public class Father{
    public void f1(Object o){
         System.out.println("Object of Father");
    }
    public void f1(double[] d){
        System.out.println("double[] of Father");
    }
}  

 子类

public class Son extends Father{
     public void fi(Object o){
          System.out.println("Object of Son");
     }
}

 测试类

public class Demo{
	public static void main(String[] args) {
		double []d = {1.2,3.5};
		Father f = new Son();
		Father father = new Father();
		Son son = new Son();
		f.f1(d);//输出double[] of Father
		father.f1(d);//输出double[] of Father
		son.f1(d);//输出double[] of Father
	}
}

 

      f.f1(d);输出double[] of Father,这里既是动态绑定也是上转型,下面再做介绍。

      father.f1(d);输出double[] of Father,这个是肯定的,不用介绍。

      son.f1(d);输出double[] of Father,这是为什么呢,Son类里面有f1(Object o)方法,传进去的double数组也适合。这个就解释了动态绑定,调用f1()方法前,先列出Son及Son的父类Father中所有f1()方法,然后看哪个合适,其实Son和Father中的f1()方法都合适,那么JVM就会选出最合适的一个。我们可以看出不管传入什么参数,f1(Object o)方法都合适,但是f1(double[] d)不一定适合,可以说第二个方法精度更高,所以在传入一个double数组时,第二个方法更合适。我们都知道继承后,如果对象没在自己类找到方法会在父类中找,找到的话就调用父类中的方法。所以son虽然是Son类对象,但是父类Father中有更合适的方法,当然就会调用父类中更合适的方法。

      如果在本类和父类及更上层都找不到合适的方法,则编译阶段就无法通过。

 

 

      下面来介绍一下向上转型:

 

      向上转型就是创建父类引用,然后将子类对象赋给这个父类引用,再调用方法,如果子类重写了该方法,那么执行子类方法,如 果子类没有重写,那么执行父类方法。就像上面例子,f在子类中没有找到该合适方法,那么就执行父类合适的方法,如果父类中没有合适方法,那么就执行父类的父类及上层的方法。

      1.虽然Father f 这里创建的是父类的引用,但是给其赋了子类对象,所以f指的是子类对象。

      2.变量是可以被继承的,但是不能被覆盖(重写),如:

         父类中有:public String str = "父类";

         子类中有:public String str = "子类";

         测试类中有:Father f = new Son();       System.out.println(f.str);

      输出的当然是"父类",这会是很多人一下迷茫了,上面明明说了f是子类的对象,那么f.str当然调用的是子类的变量了,这里调用的为什么是父类的变量呢?接着往下看:

 

父类:

public class Person {
	public String temp = "人类临时变量";
	public void say(){
		System.out.println("人类说话方法");
	}
	public void eat(){
		System.out.println("人类吃饭方法");
	}
}

 子类:

public class Student extends Person{
	public String temp = "学生临时变量";
	public String only = "学生独有变量";
	public void say(){
		System.out.println("学生说话方法");
	}
	public void eat(){
		System.out.println("学生吃饭方法");
	}
	public void study(){
		System.out.println("学生学习方法");
	}
}

 测试类

public class Test {
	public static void main(String [] args){
		Person p = new Student();
		p.say();//输出学生说话方法
		p.eat();//输出学生吃饭方法
		p.study();
		System.out.println(p.temp);//输出人类临时变量
		System.out.println(p.only);
	}
}

      看上去这段代码毫无问题,其实呢第六行会报错:"The method study() is undefined for the type Person";第八行会报错:"only cannot be resolved or is not a field"。

      向上转型会使子类对象遗失和父类不同的属性和方法,所以会报错。子类中的属性是子类自己独有的属性,因为属性是不能被重写的(上面说了),所以在上转型中,子类丢了这个属性,所以调用的当然是父类的属性了。而方法呢,子类重写了某方法,在上转型中,对象调用该方法,当然是执行的子类中重写的方法,如果没重写,那么肯定是执行父类的方法。

      那么既然会丢失子类独有的属性和方法,这不是违背了多态么?为什么还要用呢?不用上转型,就丧失了面向抽象的编程特色降低了可扩展性(这个我还不是很清楚),其实不仅仅如此,向上转型还可以减轻编程工作量,请看下面的例子:

 

父类

public class Monitor{//显示器类
	public void displayText() {}
	public void displayGraphics() {}
}

 子类1

public class LCDMonitor extends Monitor {//液晶显示器类
	public void displayText() {
		System.out.println("LCD display text");

	}
	public void displayGraphics() {
		System.out.println("LCD display graphics");
	}
}

 子类2

public class CRTMonitor extends Monitor {//阴极射线管显示器类
	public void displayText() {
		System.out.println("CRT display text");
	}
	public void displayGraphics() {
		System.out.println("CRT display graphics");
	}
}

 如果没有上转型

public class MyMonitor {
	public static void main(String[] args) {
		run(new LCDMonitor());
		run(new CRTMonitor());
	}
	public static void run(LCDMonitor monitor) {
		monitor.displayText();
		monitor.displayGraphics();
	}
	public static void run(CRTMonitor monitor) {
		monitor.displayText();
		monitor.displayGraphics();
	}
} 

你会发现上述代码有很多重复代码,而且也不易维护。。。。如果有了上转型呢

public class MyMonitor {
	public static void main(String[] args){
		run(new LCDMonitor());//向上转型
		run(new CRTMonitor());//向上转型
	}
	public static void run(Monitor monitor){//父类实例作为参数
		monitor.displayText();
		monitor.displayGraphics();
	}
}

由此可见向上转型的强大吧。。。嘿嘿嘿

 

      如果说要用子类独有的属性和方法,那当然创建子类对象,像前面的例子:创建的是Son son = new Son();  那么要调用父类中继承来的属性,就用super.属性,这样就得到的父类中的属性。如果子类没重写父类方法,当调用的时候,自动调用的父类中的该方法,如果重写了,用super.方法,调用父类中的该方法。

分享到:
评论

相关推荐

    Vue.js样式动态绑定实现小结

    在Vue.js中,样式动态绑定是实现界面变化的关键特性之一。Vue.js提供了灵活的方式来根据数据的变化动态地切换和应用CSS类和内联样式。 首先,Vue.js核心概念之一是数据驱动。数据驱动意味着当你修改数据时,视图会...

    layui动态绑定事件的方法

    本文将介绍使用layui框架来实现动态绑定事件的方法,并探讨其中的关键技术点。 首先,我们需要了解动态创建DOM元素后,原有的事件绑定可能不会生效。这是因为事件监听器是在元素创建时就绑定的,而对于后来添加到...

    Java动态绑定和静态绑定.doc

    在Java编程语言中,动态绑定和静态绑定是两个重要的概念,它们涉及到方法调用和多态性。了解这两个概念对于深入理解面向对象编程至关重要。本文将详细探讨它们的区别,并通过实例来阐述它们的工作原理。 首先,让...

    Delphi 动态绑定事件处理函数过程

    在 Delphi 编程环境中,动态绑定事件处理函数是一个强大的特性,它允许程序在运行时动态地连接事件和对应的处理函数,而不是在编译时静态地确定。这为开发提供了更大的灵活性,特别是在处理不确定数量的对象或者需要...

    动态绑定实现原理2

    动态绑定简化了多态行为的实现,使得代码更易于维护和扩展,因为我们可以用父类引用处理子类对象,而无需关心具体的子类类型。 总的来说,Java的动态绑定机制通过对象内存模型中的方法表和运行时类型信息,实现了在...

    echarts 属性全动态设置 数据动态绑定

    java实现对echarts 属性全动态设置 数据动态绑定。封装echarts 的绘图方法,使得js只需要getLine(data),getBar(data)等就可以绘制图形。echarts上的所有属性都可以在java中设置。

    ASP.Net实现SQL动态绑定Echarts图表Demo完整源码

    【ASP.Net实现SQL动态绑定Echarts图表Demo完整源码】是一个示例项目,它演示了如何在ASP.Net环境中结合Echarts图表库、C#、SQL和JSON技术来动态展示数据库中的数据。该项目的核心目标是利用后端服务器处理程序获取...

    dataGridView动态绑定数据下拉框

    本话题将深入探讨如何实现“dataGridView动态绑定数据下拉框”的功能,即在dataGridView的某一列展示一个动态生成的下拉框,其内容来源于数据库字段,并且能够与文件列名建立对应关系,从而实现数据的导入。...

    WinForm中comboBox控件数据绑定实现方法

    Dictionary也可以用来实现comboBox控件数据绑定,但是需要借助类BindingSource来完成绑定。例如: ```csharp Dictionary, string> kvDictonary = new Dictionary, string>(); kvDictonary.Add(1, "11111"); ...

    treeview动态数据绑定

    在IT领域,特别是软件开发中,TreeView控件是一种常见的用户界面元素,用于展示...在学习和实践过程中,务必注意数据源的正确配置、数据绑定表达式的编写以及事件处理的合理运用,这些都是实现高效动态数据绑定的关键。

    基于ReportViewer+C#实现的动态绑定RDLC 的数据报表程序代码

    本项目是基于ReportViewer控件和C#编程语言实现的动态绑定RDLC数据报表程序,让我们来深入探讨这个系统的实现原理及关键知识点。 1. **ReportViewer控件**:ReportViewer是Microsoft提供的一种用于创建、设计和查看...

    Python类的动态绑定实现原理

    Python 类的动态绑定是其面向对象特性的重要组成部分,它允许在程序运行期间改变类的属性和方法,使得代码更加灵活。动态绑定的概念是指在实例访问类的属性时,Python 会在运行时查找并绑定相应的属性到实例上。这种...

    C++动态绑定解密

    只有被声明为`virtual`的成员函数才能被重写,并且能够实现动态绑定。 - **虚表**:每个具有至少一个虚函数的类都有一个虚表。虚表是一张包含虚函数地址的表。每个对象都有一个指向其所属类虚表的指针。 - **虚函数...

    WPF后台动态绑定ListView数据源

    你可以将任何实现了`IEnumerable`接口的对象(如`ObservableCollection<T>`)绑定到ListView的`ItemsSource`,从而实现数据的动态更新。 以下是一些关键步骤来实现动态绑定: 1. 创建数据模型:定义一个类,表示你...

    Accordion分组菜单折叠未实现数据库动态绑定功能

    然而,如果Accordion菜单没有实现数据库动态绑定功能,这意味着菜单可能只能显示静态、预定义的数据,无法根据用户的请求或者数据的变化进行实时更新。 实现Accordion分组菜单与数据库动态绑定功能的关键在于结合...

    Java方法的动态绑定与静态绑定

    要理解向上转型又引出了动态绑定。从动态绑定又引出了静态绑定。  程序绑定的概念:  绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定...

    Cocos2d-js实现动态绑定CocostudioUI控件和事件

    Cocos2d-js实现动态绑定CocostudioUI控件的过程通常包括以下步骤: 1. **加载UI资源**:首先,你需要使用Cocos2d-js的UILoader类来加载Cocostudio创建的UI资源。`UILoader`是一个专门用于加载Cocostudio UI文件的...

    Java向上转型和向下转型实例解析

    向上转型后父类的引用所指向的属性是父类的属性,如果子类重写了父类的方法,那么父类引用指向的或者调用的方法是子类的方法,这个叫动态绑定。 向上转型后父类引用不能调用子类自己的方法,就是父类没有但是子类的...

    用户选中商品,实现动态绑定,点击一个一个往后进行索引

    在Web开发中,实现"用户选中商品,实现动态绑定,点击一个一个往后进行索引"的功能是一项常用的技术,尤其适用于商品列表等大数据量场景,帮助用户快速定位和浏览商品。这一功能通常涉及到JavaScript(JS)、jQuery...

Global site tag (gtag.js) - Google Analytics