Java学习——37、类的多态(二)
类型的多态主要体现在:子类是一种父类类型。
子类通过继承扩充和发展了它的父类,子类是父类的一种特殊类型。
1、子类对象即是父类对象
子类对象包含了父类的所有成员,包括成员变量和成员方法,所以子类对象也是父类对象。
反之不然。
父类对象不是子类对象。
可以用关键字instanceof来判断一个实例是否属于某个类。
例:
简单起见,本例中的类没有任何成员。
class Person{
}
public class Student extends Person{
public static void main(String args[]){
Person p=new Person();
Student s=new Student();
System.out.println(s instanceof Person);
System.out.println(p instanceof Student);
}
}
其运行结果如下:
true
false
因为p是Person的对象,s是Student的对象,而Student类继承自Person类。故s也是Person的实例,而p却不是Student的实例。
2、父类对象引用子类实例
子类对象也是父类对象,说明父类对象可以引用子类实例。但反过来不行。
例:
class Person{
private String name;
public Person(){
this.name="张熹熹";
}
public void show(){
System.out.println("姓名:"+name);
}
}
public class Student extends Person{
private String number;
public Student(){
number="123";//默认调用父类的Person()
}
public static void main(String args[]){
Person p=new Student();
p.show();
Student s=new Student();
s.show();
}
}
其运行结果为:
姓名:张熹熹
姓名:张熹熹
在main方法中,p中Person类的对象,但引用的是Student类的实例。S是Student类的对象,引用的也是Student类的实例。
3、编译时多态和运行时多态
根据何时能确定到底执行的是多态中的哪一个方法,分为两种情况:编译时多态和运行时多态。
如果在编译时能够确定执行多态方法中的哪一下,就称为编译时多态。
否则,称为运行时多态。
方法的重载属于编译时多态,因为在编译时,Java虚拟机已经能够根据参数类型和参数个数来匹配到底用的是哪一个重载的方法。
方法覆盖有两种多态性,如果创建的对象与引用的实例为同一个类,为编译时多态,如下:
Student s=new Student();
此时如果有s.show();在编译时Java虚拟机就可以判定此show()方法为Student这个类的,如果Student中没有这个方法,则沿着继承的顺序往上查找。
但如果创建的对象与引用的实例不为同一个类,为运行时多态。
例:Person p=new Student();
p为Person类的对象,但引用的却是Student类的实例。
若此时调用p.show(),那么这个show()方法是在Student类中的show()方法呢,还是Person类中的show()方法呢?这就是运行时的多态。
程序运行时,Java从实例所属的类开始寻找匹配的方法执行,如果当前类中没有匹配方法,则沿着继承关系逐层向上,依次在父类或各祖先类中寻找匹配方法,直到Object类。
故上面代码:
Person p=newStudent();
p.show();//从实例所在的类Student开始寻找,如果Student类中有方法show(),则执行;否则,沿着继承关系向上,在Student类的父类Person中找,如果Person类中有方法show(),则执行;否则,沿着继承关系继续向上,直到Object类为止。
4、多态的方法实现
以下例说明:
class Person{
private String name;
public Person(){
this.name="张熹熹";
}
public String toString(){
return"姓名:"+name;
}
}
public class Student extends Person{
private String number;
public Student(){
number="123";//默认调用父类的Person()
}
public String toString(){
super.toString();
return"学号:"+number;
}
public static void main(String args[]) {
Person p=new Person();
System.out.println(p.toString());//编译时多态,因为p为Person类对象,引用的也是Person类的实例,故在编译时便知是person类中的toString()方法
Persons=new Student();//父类对象引用子类实例
System.out.println(p.toString());//运行时多态,s为Person类对象,但引用的是Student类的实例,在运行时,着先在实例所在的类Student中找toString()方法,有,即执行。
}
}
其运行结果如下:
姓名:张熹熹
姓名:张熹熹