1、对象的多态性
核心内容为:Java对象的向上转型机制
(1)例1:
class Person{
public void print(){
System.out.println("1.Person类的print方法");
}
}
class Student extends Person{
public void print(){
System.out.println("2.Student类的print方法");
}
}
public class Text1{
public static void main(String[] args){
Person per = new Student();//向上转型
per.print();
}
}
//运行结果:
//2.Student类的print方法
Java中使用了向上转型机制,实现对象的多态性,通过父类对象的引用指向子类对象,即可直接调用子类对象重写的方法。
(2)例2:
//参数统一化
class Person{
public void print() {
System.out.println("1.Person类的print方法");
}
}
class Student extends Person{
public void print(){
System.out.println("2.Student类的print方法");
}
}
class Worker extends Person{
public void print(){
System.out.println("3.Worker类的Print方法");
}
}
public class Text2{
public static void main(String[] args){
fun(new Person());//Person per = new Person();
fun(new Student());//Person per = new Student();//向上转型 Student类 转为 Person类
fun(new Worker());//Person per = new Worker();//向上转型 Worker 类 转为 Person类
}
public static void fun(Person per){
per.print();
}
}
//运行结果:
//1.Person类的print方法
//2.Student类的print方法
//3.Worker类的Print方法
向上转型的核心在于使用哪个类型的构造器new的空间并且调用方法是否被重写。
向下转型机制有安全隐患不建议使用。
2、方法的多态性
多态分成两类
(1)前期绑定(方法重载)
又称为编译时多态。
class Person{
public void say(){
}
public void say(String s){
}
public void say(String s1, String s2){
}
}
类似于C++的静态多态。
(2)后期绑定(方法重写)
又称为动态绑定/运行时绑定。
触发的三个必要条件:
- 继承
- 方法重写
- 父类引用指向子类对象
子类Student重写了父类Person的方法print(),父类对象的引用per指向子类对象Student(),调用per的print()方法时实际上使用的是Student的print()。运行时才知道per要绑定的是Student对象。class Person{
public void print(){
System.out.println("1.Person类的print方法");
}
}
class Student extends Person{
public void print(){
System.out.println("2.Student类的print方法");
}
}
public class Text1{
public static void main(String[] args){
Person per = new Student();//向上转型
per.print();
}
}
//运行结果:
//2.Student类的print方法
缺陷:
(1)私有方法覆盖问题
私有方法无法覆盖因此不能实现重写,此时实现多态会失败,依然执行的是父类的私有方法。要小心父类的私有方法不能跟子类的方法重名。
(2)域和静态方法
方法调用时只能使用普通的调用,super之类的其他调用会使得多态失败。
3、构造器和清理的多态性
(1)构造器复用类中已提及,构造器连接从子类开始向上链接,运行时从根父类开始向下允许每一层构造器。
(2)清理
子类的清理方法必须调用父类的清理方法,然后再单独清理子类的内容,否则会出现父类内容未清理的情况。
4、协变返回类型
多态实现的同时,方法的返回值类型type可以被改变,此时,父类对象引用调用方法时,返回值的类型可以是type也可以是type的子类。
package Animal;
public class CovariantDemo {
public static void main(String[] args) {
Animal animal=new Animal();
Food food=animal.behavior();
food.eat();
Dog dog=new Dog();
Bone bone=dog.behavior();
bone.eat();
}
}
//基类
class Animal{
public Food behavior(){
System.out.println("Animal:");
return new Food();
}
}
//子类
class Dog extends Animal{
@Override
public Bone behavior(){
System.out.println("Dog:");
return new Bone();
}
}
class Food{
public void eat(){
System.out.println("Animal like to eat food");
}
}
class Bone extends Food{
@Override
public void eat(){
System.out.println("Dogs like to eat bones");
}
}
这基于里氏替换原则:任何父类可以出现的地方,子类也可以出现。