多态
多态存在的三个必要条件:继承,重写,父类引用指向子类的对象
使用父类类型的引用指向子类的对象
该引用只能调用父类中定义的方法和变量
如果子类重写了父类的这个方法,那么在父类类型的引用调用这个方法的时候,将会调用子类中的方法
//定义父类
public class Employee {
String name;
String address;
int n;
//父类的构造函数
public Employee(String name,String address,int n){
System.out.println("Employee 的构造函数");
this.name = name;
this.address = address;
this.n = n;
}
//定义父类中的方法
public void mainCheck(){
System.out.println("address:"+this.address+"name: "+this.name);
}
public String getAddress(){
return address;
}
public String getName(){
return name;
}
}
//定义子类
public class Salary extends Employee{
double salary = 0.00d;
//定义子类的构造函数
Salary(String name,String address,int n,double salary){
super(name,address,n);
this.salary = salary;
}
//重写父类的方法
public void mainCheck(){
System.out.println("员工 "+getName()+" 的年薪是 "+this.salary);
}
//创建父类和子类的实例对象
public static void main(String[] args){
Salary s = new Salary("sandy","shanghai",1,433.22);
Employee e = new Salary("wendy","hanghzou",3,77979.33);//向上转型
Employee e1 = new Employee("Jay","kunming",3);
s.mainCheck();//调用子类重写过的方法
e.mainCheck();//调用子类重写过的方法
e1.mainCheck();//调用父类重写过的方法
Salary s1 = (Salary)e;//向下转型
s1.mainCheck();//调用子类重写过的方法
}
}
运行结果:
Employee 的构造函数
Employee 的构造函数
Employee 的构造函数
员工 sandy 的年薪是 433.22
员工 wendy 的年薪是 77979.33
address:kunmingname: Jay
员工 wendy 的年薪是 77979.33
例子解析
-
实例中,实例化了两个 Salary 对象:一个使用 Salary 引用 s,另一个使用 Employee 引用 e。
-
当调用 s.mailCheck() 时,编译器在编译时会在 Salary 类中找到 mailCheck(),执行过程 JVM 就调用 Salary 类的 mailCheck()。
-
因为 e 是 Employee 的引用,所以调用 e 的 mailCheck() 方法时,编译器会去 Employee 类查找 mailCheck() 方法 。
-
在编译的时候,编译器使用 Employee 类中的 mailCheck() 方法验证该语句, 但是在运行的时候,Java虚拟机(JVM)调用的是 Salary 类中的 mailCheck() 方法。
以上整个过程被称为虚拟方法调用,该方法被称为虚拟方法。
Java中所有的方法都能以这种方式表现,因此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。