深入解析Java多态进阶学习

作者:世界尽头与你 时间:2022-05-16 16:06:55 

1.动态绑定机制

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

实例A

我们来看一个实例:

深入解析Java多态进阶学习

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

深入解析Java多态进阶学习

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

实例B

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

深入解析Java多态进阶学习

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

深入解析Java多态进阶学习

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

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

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

实例C

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

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

深入解析Java多态进阶学习

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

深入解析Java多态进阶学习

那么这里有一个问题,此处的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正在管理!

来源:https://blog.csdn.net/Gherbirthday0916/article/details/125743890

标签:Java,多态
0
投稿

猜你喜欢

  • C#二进制序列化实例分析

    2022-09-21 01:43:38
  • C#中重载与重写区别分析

    2023-11-01 17:43:05
  • JAVA中的静态代理、动态代理以及CGLIB动态代理总结

    2023-04-03 14:33:39
  • C# 三种序列化方法分享

    2022-09-21 03:43:05
  • Spring Boot中利用JavaMailSender发送邮件的方法示例(附源码)

    2023-05-13 02:13:08
  • Java为什么占用四个字节你知道吗

    2021-06-16 18:05:22
  • Spring Security中使用authorizeRequests遇到的问题小结

    2023-10-07 04:23:45
  • Android实现为Notification加上一个进度条的方法

    2022-12-14 00:39:01
  • 利用Spring boot如何创建简单的web交互应用

    2023-07-15 12:47:00
  • Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩效果

    2021-09-12 01:04:16
  • java如何将int数组转化为Integer数组

    2021-07-19 04:22:37
  • java获取注册ip实例

    2023-11-03 23:01:12
  • Spark SQL关于性能调优选项详解

    2021-11-05 22:32:56
  • java去除字符串中的空格、回车、换行符、制表符的小例子

    2022-04-13 12:33:44
  • Android Splash界面白屏、黑屏问题的解决方法

    2022-03-24 07:14:44
  • java明文密码三重加密方法

    2022-09-01 05:59:26
  • 浅谈Android Studio 4.1 更新内容

    2021-09-17 11:27:30
  • Android实现ImageView图片双击放大及缩小

    2022-04-07 10:34:06
  • 使用C#发送Http请求实现模拟登陆实例

    2023-06-22 22:25:07
  • C#中如何连接海康威视

    2022-12-13 20:48:44
  • asp之家 软件编程 m.aspxhome.com