miracle just wanna be better

从深层理解多态

2019-11-01
miracle

方法调用

在java中,方法调用有两类,动态方法和静态方法

静态方法:对类的静态方法的调用,在编译时就已经确定好了具体的调用方法,是静态绑定的
动态方法:需要有方法调用所作用的对象,是在调用得时候才确定具体的方法,是动态绑定的
多态就是动态方法的调用

多态概念

多态有两种:类内部之间的多态和类之间的多态
多态是面向对象编程语言的重要特性,他允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定

  1. java方法的重载(类内部之间的多态): 在类中可以创建多个方法,他们具有相同的名字,但可以有不同的参数列表,返回值类型
  2. java方法的重写(父类与子类之间的多态): 子类可以继承父类中的方法,但有时子类不想继承,而是做一定的修改,就需要方法的重写,重写的参数列表不可以修改.
    jdk7以后返回类型可以是父类返回值的派生类
    修饰符不能小于父类方法的修饰符

类之间的多态

继承和接口方式实现多态

public class Father {
	public void dealHouse(){
		System.out.println("父亲管理房子");
	}
	public static void main(String[] args) {
		Father father=new Father();
		Father sonA=new sonA();
		Father sonB=new sonB();
		father.dealHouse();
		sonA.dealHouse();
		sonB.dealHouse();
	}
}
class sonA extends Father{
	@Override
	public void dealHouse(){
		System.out.println("A儿子管理房子");
		
	}
}
class sonB extends Father{
	@Override
	public void dealHouse(){
		System.out.println("B儿子管理房子");
	}

结果

  • 父亲管理房子
  • A儿子管理房子
  • B儿子管理房子

分析多态

  1. jvm内存

不论是类内部之间还是类之间的多态,发现这些方法的名字都是一样的,那程序在调用的时候是如何区分的呢

java编译器将代码编译成class文件,通过类装载器把class装载到jvm中,最后执行,最关键的是方法区
方法区存的是类的信息

方法区中的类类型信息和堆中的对象是不同的,在方法区中,class的类型信息只有唯一的实例,而在堆中可以有多个该类的对象,方法区中的类型信息就是一个模板

Father sonA=new sonA();
Father sonB=new sonB();
当程序运行到Father sonA=new sonA()这里就出现了多态,这是因为编译时看到Father,但是运行时new出来一个sonA类,两种类型不一样

  1. Father sonA是一个引用类型,存在了java栈中的本地变量表中
  2. new sonA其实创建了一个实例对象,存储在了java堆中
  3. sonA的类类型数据存在方法区中

调用流程:

  1. 虚拟机通过reference(Father的引用)查询java栈中的本地变量表,得到堆中的对象类型数据的指针
  2. 通过到对象的指针找到方法区中的对象类类型数据
  3. 查询方法表定位到sonA类的方法运行

方法表

方法表存储在方法区中,他是实现多态的关键,里面保存的是实例方法的引用,是直接引用,java虚拟机在执行程序的时候通过这个方法表来确定一个多态方法

每个类都有一个方法表,子类中方法表不同的方法指向不同的类类型信息,继承自Object的就指向Object,继承自Father就指向Father(也就是包含了父类的方法dealHouse),那为什么指向的是父类dealHouse,执行的确实子类的dealHouse方法呢,
当Son类的方法表会有一个指向父类dealHouse方法的指针,同时也有指向自己dealHouse方法的指针,这时候新的数据会覆盖原有的数据,也就是说原来指向Father.dealHouse的引用会被替换成son.dealHouse的引用

注意

上面是对继承实现多态的分析,如果是接口实现的,过程不一样.jvm对于接口的方法调用是采用搜索方法表的方式,如,要在Father接口的方法中找到dealHouse方法,必须搜索Father的整个方法表,从效率上说,接口方法的调用慢于类方法的调用


上一篇 java内存结构

下一篇 策略设计模式

Comments

Content