目录
方法或对象具有多种形态,是面向对象的三大特征之一,多态是建立在封装和继承之上的。
1、方法的多态,如方法的重写和重载。
①、使用方法重载实现
- public class Test01 {
- public static void main(String[] args) {
- B b = new B();
- System.out.println(b.sum(1,2));
- System.out.println(b.sum(1,2,3));
- }
- }
-
- class B {
- public int sum(int n1,int n2){
- return n1 + n2;
- }
- public int sum(int n1,int n2,int n3){
- return n1 + n2 + n3;
- }
- }
上述代码:通过传入参数的个数不一样,调用的方法也不一样,通过重载体现了方法的多态。
②、使用方法重写实现
- public class Test01 {
- public static void main(String[] args) {
- B b = new B();
- A a = new A();
- a.say();
- b.say();
- }
- }
- class A{
- public void say(){
- System.out.println("A类的say方法被调用...");
- }
- }
- class B extends A{
- public void say(){
- System.out.println("B类的say方法被调用...");
- }
- }

从结果就能看出,虽然是同一方法,但根据对象不一样调用结果是不一样的。
2、对象多态
1、一个对象的编译类型和运行类型可以不一致。
2、编译类型在定义对象时,就确定了,不能改变
3、运行类型是可以变化的。
4、编译类型看定义时 = 号的左边,运行类型看 = 号的右边。
- public class Animal {
- public void cry(){
- System.out.println("动物种类。。。");
- }
- }
- public class Dog extends Animal {
-
- public void cry() {
- System.out.println("小狗是狗类");
- }
- }
- public class Cat extends Animal {
-
- public void cry() {
- System.out.println("小猫是猫类");
- }
- }
- public class Test02 {
- public static void main(String[] args) {
- //animal的编译类型是Animal,运行类型是Dog
- Animal animal = new Dog();
- animal.cry();//因为animal的运行类型是Dog,所以会去调用Dog类的cry方法。
- animal = new Cat(); //因为animal的运行类型发生改变,所以会调用Cat里的cry方法
- animal.cry();
- }
- }
运行结果:

多态的前提是:两个对象(类)存在继承关系。
多态向上转型
①、本质上,父类的引用指向了子类对象。
②、在语法上:父类类型 引用名 = new 子类类型();
③、编译类型看左边,运行类型看右边,可以调用父类中的所有成员,但必须遵守访问权限,不能调用子类中特有成员,最终运行效果看子类的具体实现。

多态向下转型
①、在语法上:子类类型 引用名 = (子类类型)父类引用
②、只能强转父类引用,不能强转父类对象
③、要求父类的引用必须指向的是当前目标类型的对象
④、当向下转型后,可以调用子类类型中所有的成员
- public class Cat extends Animal {
-
- public void cry() {
- System.out.println("小猫是猫类");
- }
- public void eat(){
- System.out.println("小猫吃东西");
- }
- }
- public class Test02 {
- public static void main(String[] args) {
- Animal animal = new Cat();
- //向下转型
- Cat cat = (Cat) animal;
- //调用子类的特有方法
- cat.eat();
- }
- }
属性没有重写,属性的值看编译类型
- public class Test03 {
- public static void main(String[] args) {
- //这里的base编译类型是Base
- Base base = new Sub();
- System.out.println(base.count);//根据base的编译类型这里的值为1
- Sub sub = new Sub();
- System.out.println(sub.count);//2
- }
- }
- class Base{
- int count = 1;
- }
- class Sub extends Base{
- int count = 2;
- }
instanceOf比较操作符,用于判断对象的运行类型是否为某个类型或某个类型的子类型。
- public class Test04 {
- public static void main(String[] args) {
- D d = new D();
- System.out.println(d instanceof D);//true
- System.out.println(d instanceof C);//true
- //当编译类型为C时,运行类型为D时
- C c = new D();
- System.out.println(c instanceof D);//true
- System.out.println(c instanceof C);//true
-
- }
- }
- class C{ }
- class D extends C{
- }
1、当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
2、当调用对象属性时,没有动态绑定机制,哪里声明,那里使用。
- public class Test01 {
- public static void main(String[] args) {
- A a = new B();
- System.out.println(a.sum());//40 -> 30
- System.out.println(a.sum1());//30 -> 20
- }
- }
- class A{
- public int i = 10;
- //这里Java会调用动态绑定机制
- public int sum(){
- return getI() + 10;
- }
- public int sum1(){
- return i + 10;
- }
- public int getI(){
- return i;
- }
- }
-
- class B extends A{
- public int i = 20;
- // public int sum(){
- // return i + 20;
- // }
- public int getI(){
- return i;
- }
- // public int sum1(){
- // return i + 10;
- // }
- }
数组的定义类型为父类类型,里面保存的实际元素类型为子类型。
Person类
- 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;
- }
- }
Student 类
- 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() + "\t成绩:" + score;
- }
- }
Teacher类
- 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() + "\t工资" + salary;
- }
- }
PloyArray类
- public class PloyArray {
- public static void main(String[] args) {
- Person[] people = new Person[5];
- people[0] = new Person("tom",20);
- people[1] = new Student("小明",13,90);
- people[2] = new Student("小红",14,80);
- people[3] = new Teacher("老李",12,9200);
- people[4] = new Student("小美",15,91);
- //循环遍历
- for (int i = 0; i
- //这里使用了Java的动态绑定机制,
- //people[i]的编译类型是Person,而调用say方法时的运行状态由JVM决定
- System.out.println(people[i].say());
- }
- }
- }
运行结果:

在多态数组中调用子类特有的方法:
在Teacher类 新增特有的方法
- //子类特有方法
- public void teach(){
- System.out.println("老师" + getName() + "正在讲课。。。");
- }
PloyArray类
- public class PloyArray {
- public static void main(String[] args) {
- Person[] people = new Person[5];
- people[0] = new Person("tom",20);
- people[1] = new Student("小明",13,90);
- people[2] = new Student("小红",14,80);
- people[3] = new Teacher("老李",12,9200);
- people[4] = new Student("小美",15,91);
- //循环遍历
- for (int i = 0; i
- //这里使用了Java的动态绑定机制,
- //people[i]的编译类型是Person,而调用say方法时的运行状态由JVM决定
- System.out.println(people[i].say());
- //使用instanceof判断people[i]的运行类型
- if (people[i] instanceof Teacher){
- //调用子类特有方法
- ((Teacher)people[i]).teach();
- }
- }
- }
- }
运行结果:

六、多态参数
方法定义的形参类型为父类类型,实参类型允许为子类型。
Employee类
- public class Employee {
- private String name;
- private double salary;
-
- public Employee(String name, double salary) {
- this.name = name;
- this.salary = 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 double getAnnual(){
- return 12 * salary;
- }
- }
Worker类
- public class Worker extends Employee{
- public Worker(String name, double salary) {
- super(name, salary);
- }
- public void work(){
- System.out.println("普通员工" + getName() + "在工作");
- }
-
- @Override
- public double getAnnual() {
- return super.getAnnual();
- }
- }
Manager类
- 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 manage(){
- System.out.println("经理" + getName() + "在管理");
- }
-
- @Override
- public double getAnnual() {
- return super.getAnnual() + bonus;
- }
- }
- public class Test01 {
- public static void main(String[] args) {
- Worker worker = new Worker("小李", 6000);
- Manager manager = new Manager("老张", 10000, 5000);
- Test01 test01 = new Test01();
- test01.getAndAnnual(manager);
- test01.getWork(worker);
- }
- //根据对象获取年工资
- public void getAndAnnual(Employee e){
- //使用动态绑定机制
- System.out.println(e.getAnnual());
- }
- public void getWork(Employee e){
- //判断对象类型
- if (e instanceof Worker){
- ((Worker)e).work();//向下转型
- }else {
- ((Manager)e).manage();
- }
- }
- }
-
相关阅读:
mybatis-plus的多数据源sql拦截&动态表名
程序化交易(一)交易接口接入
房屋租赁管理系统的设计与实现
工业智能网关BL110应用之三十八: COM口如何配置采集Modbus协议设备
数据库MYSQL
VoLTE端到端业务详解 | VoLTE基本概念
Linux简单命令学习 -- useradd passwd userdel
磁盘空间不够引发的控制录像程序崩溃到后端的解决方式
西北主要河流水系(绿洲)流域(山区)及高程分类数据集(一)
0基础转行软件测试,如何实现月薪9.5k+
-
原文地址:https://blog.csdn.net/qq_46093575/article/details/126807020