多态(polymorphism)
多态的概念
多态是指一个程序中相同的名字表示不同的含义的情况。 多态有两种情形:
编译时多态:
重载(overload)多个同名的不同方法 如:p.sayHello(); p.sayHello("wang");
运行时多态:
覆盖(override)子类对父类方法进行覆盖 动态绑定(dynamic binding)—-也成为虚方法调用(virtual method invoking),真正的方法在运行时才确定。 在调用方法时,程序会正确地调用子类对象的方法。 多态的特点大大提高了程序的抽象程度和简洁性。
上溯造型(upcasting)
Person p = new Student();
void fun(Person p){... }
fun(new Person()); or fun(new Student());
虚方法 (virtual methods)
虚方法调用
虚方法调用,可以实现运行时的多态
子类重载了父类的方法时,运行时系统根据调用该方法的实例的类型 来决定选择哪一个方法调用。 所有的非final方法都会自动地进行动态绑定 。
public class TestVirtualInvoke {
static void doStuff(Shape s){
s.draw();
}
public static void main(String[] args) {
Shape s = new Shape();
Cricle c = new Cricle();
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 Cricle extends Shape {
void draw(){ System.out.println("Draw Cricle" ); }
}
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 Cricle
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 type 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();
}
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();
doStuff(s2);
s2.draw();
Circle c = new Circle();
c.draw();
}
}
class Shape {
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.out.println("Draw Line" ); }
}
-----------OUTPUT-----------
Draw Shape
Draw Shape
Draw Shape
Draw Shape
Draw Shape
Draw Circle