Java面向对象的三大基本特征是:封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism),这三大基本特征是学习Java面向对象开发的基础和重点。本篇博客将详细介绍这三大基本特征中多态性的用法。

☍ 多态性(Polymorphism)

多态性,是面向对象中最重要的概念,也是三大基本特征中最难的一个。简单的理解就是同一个行为具有多个不同表现形式或形态的能力,或者说多态就是同一个接口,使用不同的实例而执行不同操作。

▴ 对象的多态性

☃ 父类的引用指向子类的对象(可以直接应用在抽象类和接口上)

☃ 子类的对象可以替代父类的对象使用

☄ 一个变量只能有一种确定的数据类型

☄ 一个引用类型变量可能指向(引用)多种不同类型的对象

Person p = new Student(); //父类Peson变量p指向Student对象

▴ Java引用变量有两个类型

☃ 编译时类型:由声明该变量时使用的类型决定(看‘=’左边)

☃ 运行时类型:由实际赋给该变量的对象决定(看‘=’右边)

//父类 --> 子类 Person-->Student-->GirlStudent
// -->BoyStudent
编译时类型 Person p1 = new Student(); 运行时类型
Person p2 = new GirlStudent();
Person p3 = new BoyStudent();
Student s1 = new GirlStudent();
Student s2 = new BoyStudent();

◌ 若编译时类型和运行时类型不一致,就出现了对象的多态性

▴ 多态情况

☃ 看左边:看的是父类的引用,ctrl + 鼠标选中指定方法进入的是父类(父类中不具备子类特有的方法)

☃ 看右边:看的是子类的对象(实际运行的是子类重写父类的方法)

✦ 通过多态创建的对象拥有父类全部的属性和方法以及子类重写父类的方法,但是不具备子类特有的方法

✦ 多态是针对方法重写的,对于属性没用,最终调用的依然是父类的属性(即使存在同名属性)

public class Test{
public static void main(String args[]){
Person p = new Student();
System.out.println(p.id); //输出为1111
}
}
class Person{
int id = 1111;
}
class Student extends Person{
int id = 1122;
}

▾ 向上转型(upcasting)

☃ 子类可看做是特殊的父类 , 所以父类类型的引用可以指向子类的对象:向型上转型(upcasting)

☃ 向上转型时,父类变量指向子类对象,但是却无法使用子类特有的方法和属性,能够使用子类重写父类的方法

▴ 多态性的应用场景

☃ 多态性的使用是虚拟方法调用(Virtual Method Invocation)

☃ 虚拟方法调用:子类中定义了与父类同名同参数的方法(方法的重写),在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的

☃ 方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法

public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(test.getInstance(1));
}
//动态返回Animal对象(多态)
public static Animal getInstance(int key) {
switch (key) {
case 1:
return new Cat();
case 2:
return new Dog();
default:
return null;
}
}
//掉用对象方法
public void func(Animal animal) {
animal.eat();
animal.shout();
}
}
//Animal类
class Animal{
public void eat() {
System.out.println("动物吃东西");
}
public void shout() {
System.out.println("动物叫");
}
}
//Dog类继承Animal
class Dog extends Animal{
public void eat() {
System.out.println("狗吃骨头");
}
public void shout() {
System.out.println("汪汪汪");
}
public void dog() {
System.out.println("