浅谈java的多态机制


最近在学习java的反射机制的东东,突然觉得java的RTTI和多态有着很大的联系,特此发表这篇博客 ,一来方便自己以后查看,同时也给大家分享一下学习的经验。

第一:要理解多态,那么就要先理解java的运行时的类型和编译时的类型,那么我们先看一个demo。 

package com.yang.pack;
class Person{
	public String name="bruce";
	public void language(){
		
		System.out.println("English");
		
	}
}
class Coder extends Person{
	public String name="yangming";
	public void language(){
		System.out.println("Chinese");
		
	}
	
}
public class PolymorphismDemo {
	public static void main(String[] args) {
		Person person = new Coder();//向上转型
		System.out.println(person.name);
		person.language();

	}

}

结果是bruce和chinese。问题就出现在这里了为什么同样是person引用但是为什么对于方法和成员变量的处理不一样呢?那么我们在上述代码中来判断一下person引用的类对象是谁。

 

package com.yang.pack;
class Person{
	public String name="bruce";
	public void language(){
		
		System.out.println("English");
		
	}
}
class Coder extends Person{
	public String name="yangming";
	public void language(){
		System.out.println("Chinese");
		
	}
	
}
public class PolymorphismDemo {
	public static void main(String[] args) {
		Person person = new Coder();//向上转型
		System.out.println(person.name);
		person.language();
		System.out.println(person.getClass());

	}

}
这次输出中多了class com.yang.pack.Coder,显然通过类对象进行判断person引用时属于Coder类的,关于类对象我会在下一篇博客谈谈。那么既然person引用是Coder类型的那么为什么对于常量的处理还是遵循着父类的成员变量呢?这就涉及到了一个编译时类型的概念,对于上面的demo。Person person = new Coder();这里面的person引用存在着两种形态,一个是编译时的形式,一个是运行时的形式,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,会出现所谓的多态。 引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。这也就是RTTI的宗旨,在运行时决定类型。向上转型的过程就是接口在缩小的过程,当然不是完全消失,只是屏蔽了,也就是说变量的引用只能调用子类和父类公共的接口,如果非要利用编译时常量调用非公共的接口的话,编译时通不过的。因为父类不知道子类扩展了父类,它只知道父类拥有的变量和方法,有一点要记住,在程序没有运行时那么代表的就是编译时的形态。只有在运行时多态才会表现出来,这再一次证明了RTTI。从内存角度上来说,在继承的过程中,子类继承了父类的所有方法和成员变量,在方法的继承中,假设子类没有对父类方法的覆盖,那么父类直接将父类的方法拿到子类的内存中去,但是一旦子类覆盖了父类的方法那么父类的方法将不再拿到子类中去,但是对于变量而言是不存在覆盖的,如果子类和父类的变量成员相同,那么子类中存在两个同名的变量,调用时调用哪个变量是有编译时变量决定的。关于java的多态就总结这些,这是我第一次写博客,一孔之见,如有错误之处,还请指教,让我们一同进步。

你可能感兴趣的:(浅谈java的多态机制)