深入解析Java多态进阶学习
作者:世界尽头与你 发布时间:2022-05-16 16:06:55
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正在管理!
来源:https://blog.csdn.net/Gherbirthday0916/article/details/125743890


猜你喜欢
- Android插件开启对新Api的支持这一天小王导入了一个库,上线之后直接崩了一大片? 找到其中的问题:什么鬼哦?安卓8.0一下无法使用?
- 收费版本:Rainbow Brackets免费版本:Rainbow Brackets Lite介绍一款可以将 (圆括号) [方括号] {花括
- 代码如下:// 时间线装饰器public class TimeLineDecoration extends RecyclerView.Ite
- 前言自从国产之光fastjson频频暴雷,jackson json的使用是越来越广泛了。尤其是spring家族把它搞成了默认的JSON处理包
- 泛型是Java中一个非常重要的内容,对于Java进阶学习是必须要掌握的知识点之所以说这个知识点重要,如果你有过阅读过一些开源框架的代码,那你
- 需要修改Main方法第一行代码的路径为你的books.xml文件绝对路径或相对路径。代码演示了XPath各种语法的使用情况books.xml
- 本文实例为大家分享了C#实现单位换算器的具体代码,供大家参考,具体内容如下一、阐述进制间转换:十六进制、十进制、八进制、二进制。长度间转换:
- 实例如下:private bool creatExcel(string xlsfile) { &nb
- 目录1、基本语法2、标识符(合法的变量名)3、关键字(保留字)4、注释5、Java 包5.1 package 语句5.2 import 语句
- 一、如何实现TCP通信要实现TCP通信需要创建一个服务器端程序和一个客户端程序,为了保证数据传输的安全性,首先需要实现服务器端程序,然后在编
- application.properties大家都不陌生,我们在开发的时候,经常使用它来配置一些可以手动修改而且不用编译的变量,这样的作用在
- 本节,我们从Rxjava使用代码入手,去结合自己已有的知识体系,加查阅部分源码验证的方式,来一起探索一下Rxjava实现的基本原理。为了本文
- 使用YZMHelper帮助类即可using System;using System.Web;using System.Drawing;usi
- 本文实例为大家分享了Android实现录音静音降噪的具体代码,供大家参考,具体内容如下需求:客户反馈产品的录音里面很多杂音(因为我们把Cod
- 要用TextView使用渐变色,那我们就必须要了解LinearGradient(线性渐变)的用法。LinearGradient的参数解释Li
- 先贴代码,后面做一些简单说明:public static string sendPostHttpRequest_2(string url,
- 最近遇到了一个问题,一份很老的代码要修改里面的变量,源码早就和开发者一起不知去向,其中引用了一些jar包导致无法直接编译,只能直接修改.cl
- 1、实现这里主要用的是反射的方法。用户要传入方法名和方法参数,我们就需要先写函数返回这些信息,最后再包装一下返回给用户。获取某一程序集下所有
- HashTable和HashMap区别第一,继承的父类不同。Hashtable继承自Dictionary类,而HashMap继承自Abstr
- 前言在Android屏幕的空间中,大部分的区域我们都是可以随意绘制,只有一部分区域是显示的固定内容:状态栏标题栏(ActionBar)页面内