深入解析Java多态进阶学习

 更新时间:2022年07月13日 16:10:56   作者:世界尽头与你  
java的动态绑定机制非常重要。这篇文章将带大家更深入的学习一下Java的多态,文中的示例代码讲解详细,对我们学习Java有一定帮助,需要的可以参考一下

1.动态绑定机制

java的动态绑定机制非常重要

实例A

我们来看一个实例:

阅读上面的代码,请说明下面的程序将输出什么结果:

程序将会输出40和30,这个实例很简单,直接看运行类型即可,该代码的运行类型为B,所以会调用B类的方法

实例B

我们将上面的代码变通一下,将子类中的如下代码块注销:

随后继承机制会访问父类的sum方法:

那么这里有一个问题,此处的getI(),会执行子类的还是父类的呢?

当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

代码的运行类型依然是B,所以此处会执行子类的getI()方法,结果输出为30

实例C

现在我们再变通以下上面的代码

再将子类中如下的代码块注销:

继承机制会执行父类的sum1方法:

那么这里有一个问题,此处的i,会使用子类的还是父类的呢?

属性没有动态绑定机制,哪里声明,哪里使用(使用当前类的)

此处的i在父类进行声明,所以会选用父类的i属性,结果为20

2.多态数组

定义:

数组的定义类型为父类类型,但是保存的实际元素类型为子类类型

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;
    }

    // 重写父类的say方法
    public String say() {
        return super.say() + '\t' + score;
    }
}

Teacher子类:

/**
 * 多态数组教师子类
 */
public class Teacher extends Person {
    private double sal;

    public Teacher(String name, int age, double sal) {
        super(name, age);
        this.sal = sal;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public String say() {
        return super.say() + '\t' + sal;
    }
}

测试多态数组的使用:

public class Test {
    public static void main(String[] args) {
        // 多态数组的使用
        Person[] persons = new Person[5];
        persons[0] = new Person("dahe",20);
        persons[1] = new Student("wangwei",11,100);
        persons[2] = new Student("zhangsan",12,60);
        persons[3] = new Teacher("wang",33,15000);
        persons[4] = new Teacher("li",55,25000);

        // 循环遍历多态数组,调用say方法
        for (int i = 0; i < persons.length; i++) {
            String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person
            // 运行类型是根据实际情况由JVM机决定
            System.out.println(out);
        }
    }
}

输出:

dahe    20
wangwei    11    100.0
zhangsan    12    60.0
wang    33    15000.0
li    55    25000.0

3.多态数组的高阶用法

现在,教师子类新增了教学方法:

public void teach() {
    System.out.println("老师:" + getName() + "正在讲课!");
}

学生子类新增了学习方法:

public void study() {
    System.out.println("学生:" + getName() + "正在学习!");
}

那么,有没有办法通过多态数组来访问他们子类对应的独有的方法呢?事实上,可以通过巧妙使用instanceof来解决:

变通一下,改变多态数组的循环操作:

// 循环遍历多态数组,调用say方法
for (int i = 0; i < persons.length; i++) {
    String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person
    // 运行类型是根据实际情况由JVM机决定
    System.out.println(out);
    if (persons[i] instanceof Student) {
        // 向下转型
        Student student = (Student) persons[i];
        student.study();
    } else if (persons[i] instanceof Teacher) {
        Teacher teacher = (Teacher) persons[i];
        teacher.teach();
    }
}

输出:

dahe    20
wangwei    11    100.0
学生:wangwei正在学习!
zhangsan    12    60.0
学生:zhangsan正在学习!
wang    33    15000.0
老师:wang正在讲课!
li    55    25000.0
老师:li正在讲课!

大功告成!多态数组即强大又完美!

4.多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型

接下来我们来演示以下多态参数的使用:

父类:

/**
 * 多态参数 - 父类
 */
public class Employee {
    private String name;
    private double sal;

    public Employee(String name, double sal) {
        this.name = name;
        this.sal = sal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    // 得到年工资的方法
    public double getAnnual() {
        return 12 * sal;
    }
}

员工子类:

/**
 * 多态参数 - 子类员工
 */
public class Worker extends Employee{
    public Worker(String name, double sal) {
        super(name, sal);
    }

    public void work() {
        System.out.println("普通员工:" + getName() + "正在工作!");
    }

    public double getAnnual() {
        return super.getAnnual();
    }
}

经理子类:

/**
 * 多态参数 - 经理子类
 */
public class Manager extends Employee{
    private double bonus; // 奖金

    public Manager(String name, double sal, double bonus) {
        super(name, sal);
        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 Test {
    public static void main(String[] args) {
        Worker zhang = new Worker("张工",1000);
        Manager milan = new Manager("milan", 5000, 2000);
        Test test = new Test();
        test.showEmpAnnual(zhang);
        test.showEmpAnnual(milan);
    }


    // 获取员工的年薪,采用多态参数
    public void showEmpAnnual(Employee e) {
        System.out.println(e.getAnnual());
    }
}

输出:

12000.0
62000.0

5.多态参数的高阶用法

我们来对上面的多态参数代码做一个完善,如果传入的是员工,则调用自己的work方法,如果传入的是经理,则调用自己的manage方法

增加一个下面的方法:

public void testWork(Employee e) {
    if (e instanceof Worker) {
        ((Worker) e).work(); // 向下转型
    } else if (e instanceof Manager) {
        ((Manager) e).manage();
    }
}

测试:

test.testWork(zhang);
test.testWork(milan);

输出:

普通员工:张工正在工作!
经理:milan正在管理!

到此这篇关于深入解析Java多态进阶学习的文章就介绍到这了,更多相关Java多态内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现世界上最快的排序算法Timsort的示例代码

    Java实现世界上最快的排序算法Timsort的示例代码

    Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。本文将详解Timsort算法是定义与实现,需要的可以参考一下
    2022-07-07
  • 详解jvm中的标量替换

    详解jvm中的标量替换

    这篇文章主要介绍了详解jvm中的标量替换,帮助大家更好的理解和使用Java虚拟机,感兴趣的朋友可以了解下
    2020-09-09
  • 图文精讲java常见分布式事务理论与解决方案

    图文精讲java常见分布式事务理论与解决方案

    对于分布式系统,最简单的理解就是一堆机器对外提供服务,相比单体服务,它可以承受更高的负载,但是分布式系统也带了一系列问题,今天带大家搞懂和分布式相关的常见理论和解决方案
    2021-11-11
  • IDEA 如何导入别人的javaweb项目进行部署

    IDEA 如何导入别人的javaweb项目进行部署

    这篇文章主要介绍了IDEA 如何导入别人的javaweb项目进行部署,本文给大家分享我的详细部署过程及遇到问题解决方法,需要的朋友可以参考下
    2023-03-03
  • Java日常练习题,每天进步一点点(5)

    Java日常练习题,每天进步一点点(5)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-07-07
  • java清除html转义字符

    java清除html转义字符

    这篇文章主要介绍了一个静态文件处理的一些便捷服务,包括 java清除html转义字符,清除html代码,从style样式中读取CSS的属性,将字符串截取指定长度,涉及log4j,common-lang类的学习
    2014-01-01
  • SpringCloud feign服务熔断下的异常处理操作

    SpringCloud feign服务熔断下的异常处理操作

    这篇文章主要介绍了SpringCloud feign服务熔断下的异常处理操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java从源码角度解析SpringMVC执行流程

    Java从源码角度解析SpringMVC执行流程

    这篇文章主要介绍了Java从源码角度解析SpringMVC执行流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • java解决请求跨域的两种方法

    java解决请求跨域的两种方法

    这篇文章主要为大家详细介绍了java解决请求跨域的两种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • 使用Spring boot标记一个方法过时

    使用Spring boot标记一个方法过时

    这篇文章主要介绍了使用Spring boot标记一个方法过时,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论