Java SE 多态
1、多态
-
方法的多态
//方法重载体现多态 A a = new A(); //这里我们传入不同的参数,就会调用不同sum方法 System.out.println(a.sum(10,20)); System.out.println(a.sum(10,20,30)); //方法重写体现多态
-
对象的多态
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时 = 号 的左边,运行类型看 = 号的右边
Animal animal = new Dog();//animal编译类型是Animal,运行类型是Dog animal = new Cat(); //animal 的运行类型变成了 Cat,编译类型仍然是 Animal
-
多态的向上转型
-
本质:父类的引用指向了子类的对象
-
语法:父类类型 引用名 = new 子类类型();
-
特点:编译类型看左边,运行类型看右边。
可以调用父类中的所有成员(须遵循访问权限)
不能调用子类中特有的成员
最终运行效果看子类(运行类型)的具体实现,
即调用方法时,按照从子类开始查找方法,然后调用,规则按方法的调用规则一致
(从子类找,子类有,则调用,子类无,则在父类找,父类有,并可以调用,则调用,父类无,从祖父类找,祖父类 有,并可以调用,则调用,祖父类无,从Object类找) 如果查找方法的过程中,找到了,但是不能访问,则报错
-
-
多态的向下转型
- 语法:子类类型 引用名 = (子类类型)父类引用;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有的成员
Animal animal = new Cat(); Cat cat = (Cat) animal;
-
属性没有重写之说!属性的值看编译类型
-
instanceOf 比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型
System.out.println(aa instanceof AA); // true
-
属性看编译类型,方法看运行类型
-
Java的动态绑定机制
-
当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
(子类中没有get方法,调用了父类的get方法,但是父类的get方法中又有一个say方法,这个say方法子类也有,则这个时候调用 子类的say方法)
-
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
-
-
多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
public class PloyArray { public static void main(String[] args){ Person[] person = new Person[5]; person[0] = new Person("jack",20); person[1] = new Student("mary",18,100); person[2] = new Student("smith",19,30.1); person[3] = new Teacher("scott",30,20000); person[4] = new Teacher("king",50,25000); //循环遍历多态数组,调用say for (int i = 0; i < person.length; i++) { //person[i] 编译类型是 Person ,运行类型是根据实际情况由JVM来判断 System.out.println(person[i].say()); //动态绑定机制 //类型判断 + 向下转型 if (person[i] instanceof Student){//判断person[i] 的运行类型是不是Student Student student = (Student)person[i];//向下转型 student.study(); }else if(person[i] instanceof Teacher){ ((Teacher)person[i]).teach(); }else if(person[i] instanceof Person){ }else{ System.out.println("你的类型有误,请自己检查..."); } } } } 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; } } 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; } //重写父类的say方法 @Override public String say() { return "学生 " + super.say() + " score =" + score; } //特有方法 public void study(){ System.out.println("学生 " + getName() + "正在学习..."); } } 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; } //重写父类的say方法 @Override public String say() { return "老师 " + super.say() + " salary =" + salary; } //特有方法 public void teach(){ System.out.println("老师 " + getName() + "正在授课..."); } } /* 运行结果 jack 20 学生 mary 18 score =100.0 学生 mary正在学习... 学生 smith 19 score =30.1 学生 smith正在学习... 老师 scott 30 salary =20000.0 老师 scott正在授课... 老师 king 50 salary =25000.0 老师 king正在授课... */
-
多态参数:方法定义的形参类型为父类类型,实参类型允许为子类类型
public class PloyParameter { public static void main(String[] args) { Worker tom = new Worker("tom", 2500); Manager milan = new Manager("milan", 5000, 200000); PloyParameter ployParameter = new PloyParameter(); ployParameter.showEmpAnnual(tom); ployParameter.showEmpAnnual(milan); ployParameter.testWork(tom); ployParameter.testWork(milan); } public void showEmpAnnual(Employee e) { //形式参数为父类类型 System.out.println(e.getAnnual()); } public void testWork(Employee e) { if (e instanceof Worker) { ((Worker) e).work(); //有向下转型 }else if(e instanceof Manager) { ((Manager) e).manager(); //有向下转型 }else { System.out.println("不做处理"); } } } public class Employee { //父类 private String name; private double salary; //月工资 public Employee(String name, double salary) { this.name = name; this.salary = salary; } //得到年工资的方法 public double getAnnual() { return 12 * salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } public class Worker extends Employee{ public Worker(String name, double salary) { super(name, salary); } public void work() { System.out.println("普通员工" + getName() + "is working"); } @Override public double getAnnual() { //普通员工没有其他收入,则直接调用父类方法 return super.getAnnual(); } } public class Manager extends Employee{ private double bonus; public Manager(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public void manager() { System.out.println("经理" + getName() + "is managing"); } //重写获取年薪的方法 @Override public double getAnnual() { return super.getAnnual() + bonus; } } /* 运行结果 30000.0 260000.0 普通员工tomis working 经理milanis managing */