Java多态和虚方法调用
多态(polymorphism)
多态的概念
·多态是指一个程序中相同的名字表示不同的含义的情况。
·多态有两种情形:
1、编译时多态:
1.重载(overload)多个同名的不同方法;
2.如:p.sayHello();p.sayHello(“wang”);
2、运行时多态:
1.覆盖(override)子类对父类方法进行覆盖
2.动态绑定(dynamic binding)也称为虚方法调用(virtual method invoking),真正的方法在运行时才确定
3.在调用方法时,程序会正确地调用子类对象的方法。
·多态的特点大大提高了程序的抽象程度和简洁性。
上溯造型(upcasting)
·是把派生类型当作基本类型处理,如:
Person p = new Sudent(); void fun(Person p){…} fun(new Person)); or fun(new Student());
虚方法(virtual methods)
虚方法调用
·虚方法调用,可以实现运行时的多态
·子类重载了父类的方法时,运行时系统根据调用该方法的实例的类型来决定选择哪一个方法调用;
·所有的非final方法都会自动地进行动态绑定
public class TestVirtualInvoke{ static void doStuff(Shape s){//Shape为形式参数类型 s.draw(); } public static void main(String[] args){ Shape s = new Shape(); Circle c = new Circle(); Triangle t = new Triangle(); Shape l = new Line();//可以将父类类型的引用指向子类的实例对象 doStuff(s); doStuff(c);//调用的时候,使用其子类实例作为参数 doStuff(t);//运行时,系统根据调用方法的实例类型,来决定哪一个方法被调用 doStuff(l); } } class Shape{ void draw(){System.out.println(“Draw Shape”);} } class Circle extends Shape{ //子类重载了父类的方法 void draw(){System.out.println(“Draw Circle”);} } class Triangle extends Shape{ void draw(){System.out.println(“Draw Triangle”);} } class Line extends Shape{ void draw(){System.out.println(“Draw Line”);} } -----------OUTPUT------------ Draw Shape Draw Circle Draw Triangle Draw Line
动态类型确定
·使用运算符 instanceof
·作用:运行时用来指出对象是否是特定类的一个实例。通过返回一个布尔值,来指出对象是否是这个特定类或者是它的子类的一个实例
·用法: flag = Object instanceof class
·如果Object是class的一个实例,则返回true,否则,返回false。
public class InstanceOf{ public static void main(String[] args){ Object things[] = new Object[3]; things[0] = new Integer(1); things[1] = new Double(1); things[2] = new String(“1”); for(int i=0; i<things.length; ++i){ System.out.println(“the type of things[“+i+”]is”+things[i].getClass()); } } } ---------------OUTPUT--------------- the type of things[0] is class java.lang.Integer the type of things[1] is class java.lang.Double the tyoe of things[2] is class java.lang.String
什么情况不是虚方法的调用
·Java中,普通方法是虚方法。既,不用做出特殊声明的方法都是虚方法。既,在被调用时是根据实际的对象实例选择调用哪个方法。
·static、private方法不是虚方法调用。因为你它们与虚方法编译后用的指令是不同的。(static是属于类的,不是具体某个类的;被private修饰的方法是不能被子类所override的)
三种非虚的方法
·static的方法,以声明的类型为准,与实例类型无关
·private方法子类看不见,也不会被虚化
·final方法子类不能覆盖,不存在虚化问题
public class TestVirtualInvoke2{ static void doStuff(Shape s){ s.draw();//由于draw是static方法,所以只跟声明的类型有关,与实例无关 } public static void main(String[] args){ Shape s = new Shape(); Triangle t = new Triangle(); Shape l = new Line(); doStuff(s); doStuff(t); doStuff(l); System.out.println(); Shape s2 = new Circle(); //只和声明的类型(Shape)有关,而跟后面的实例(Circle)无关 doStuff(s2); s2.draw(); Circle c = new Circle(); c.draw(); } } class Shape{ //把draw都改成static方法,与具体实例无关 static void draw(){System.out.println(“Draw Shape”);} } class Circle extends Shape{ static void draw(){System.out.println(“Draw Circle”);} } class Triangle extends Shape{ static void draw(){System.out.println(“Draw Triangle”);} } class Line extends Shape{ static void draw(){System.ou.println(“Draw Line”);} } -----------OUTPUT------------ Draw Shape Draw Shape Draw Shape Draw Shape Draw Shape Draw Circle