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