方法的 重载和重写 能体现多态
多态的前提是:两个对象(类)存在继承关系
2.对象的多态(核心,重点)
(1)一个对象的编译类型和运行类型可以不一致
Animal animal = new Dog();
//animal 编译类型是Animal ,运行类型是Dog
(2)编译类型在定义对象时就已经确定,不能改变;而运行类型是可以改变的
(=左边是编译类型,=右边是运行类型)
多态的向上转型
(1)本质:父类的引用指向了子类的对象
(2)语法:父亲类型 引用名 = new 子类类型();
(3)特点:可以调用父类中的所有成员(需遵守访问权限),但不能调用子类特有的成员,
因为在编译阶段,能调用那些成员是由编译类型来决定的
最终运行效果看子类(运行类型)的具体实现,即调用方法时,从子类开始查找方法
编译时,从编译类型开始查找;运行时,从运行类型开始查找
多态的向下转型
(1)语法:子类类型 引用名 = (子类类型) 父类引用
(只能强转父类的引用,不能强转父类的对象;
父类的引用必须指向的是当前目标类型的对象;
当向下转型后,可以调用子类类型中所有的成员)
注意:向下转型是在向上转型的基础上的
访问属性看编译类型 ;方法从其运行类型查找方法
java的动态绑定机制
对于属性的访问,Java中的属性访问遵循编译时类型的规则,即在编译时,编译器会根据变量的声明类型来决定它所能访问的属性。如果子类中没有重载父类的属性,那么在子类中访问父类中的属性时,会访问到父类中的属性;如果子类中重载了父类的属性,则会访问到子类中的属性。这种属性的访问方式是静态绑定(Static Binding)。
对于方法的访问,Java中采用的是动态绑定(Dynamic Binding)的方式。在编译时,编译器根据变量的声明类型确定方法的调用形式,但在运行时,JVM会根据实际的对象类型来确定所要执行的方法。如果子类中覆盖了父类的方法,那么在对子类对象调用该方法时,实际上执行的是子类中的方法,而不是父类中的方法。
当调用对象方法的时候,该方法会和该对象的运行类型/内存地址 绑定,从最开始的运行类型里先查找
当调用对象属性时,没有绑定机制,那里声明,哪里使用
总结:属性,静态方法,看编译类型
实例方法编译时看编译类型,运行时看运行类型
多态数组
(1)例子:要求创建1个Person对象,2个Student对象和2个Teacher对象,并将其放到一个数组中,并调用每个对象的say()方法
Person类
package com.zklxx.Objectpoly.polyarr;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say(){
return name + "\t" + age;
}
}
Teacher类
package com.zklxx.Objectpoly.polyarr;
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return "老师" + super.say() + "salary" + salary;
}
}
Student类
package com.zklxx.Objectpoly.polyarr;
public class Student extends Person{
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String say() {
return "学生" + super.say() + "score" + score;
}
}
package com.zklxx.Objectpoly.polyarr;
public class Ployarr {
public static void main(String[] args) {
Person[] person = new Person[5];
person[0] = new Person("jack",20);
person[1] = new Student("smith",18,100);
person[2] = new Student("Tom",18,90);
person[3] = new Teacher("hungrily",32,20000);
person[4] = new Teacher("Bob",33,21000);
for (int i = 0;i< person.length;i++){
System.out.println(person[i].say());
}
}
}
//结果
jack 20
学生smith 18score100.0
学生Tom 18score90.0
老师hungrily 32salary20000.0
老师Bob 33salary21000.0