【java基础】多态、编译类型、运行类型、强制类型转换、动态绑定关系梳理

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【java基础】多态、编译类型、运行类型、强制类型转换、动态绑定关系梳理,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

基础准备

我们先来创建2个类,分别是Employee和Manager类,Manager继承Employee

public class Employee {
    private String name;
    private double salary;

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

    public Employee() {
    }

    public double getSalary() {
        return salary;
    }
}
public class Manager extends Employee {
    private double bonus;

    public Manager(String name, double salary) {
        super(name, salary);
    }
    
    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    @Override
    public double getSalary() {
        return super.getSalary() + bonus;
    }
}

下面的说明将会以这2个类作为例子

多态

在Java程序设计语言中,对象变量是多态的(polymorphic.)。一个Employee类型的变量
既可以引用一个Employee类型的对象,也可以引用Employee类的任何一个子类的对象。

    public void t1(){
        // 这是Manager对象
        Manager ttpfx = new Manager("ttpfx", 12000);
        // 可以使用Employee进行引用
        Employee employee = ttpfx;
    }

编译类型

        // 这是Manager对象
        Manager ttpfx = new Manager("ttpfx", 12000);
        // 可以使用Employee进行引用
        Employee employee = ttpfx;

看上面代码,对于ttpfx,他的编译类型就是Manager,而emplyee的编译类型就是Employee。简单一点说,我们在定义变量时候,变量左边的数据类型就是它的编译类型

运行类型

        // 这是Manager对象
        Manager ttpfx = new Manager("ttpfx", 12000);
        // 可以使用Employee进行引用
        Employee employee = ttpfx;

        System.out.println(ttpfx.getClass());
        System.out.println(employee.getClass());

还是对于上面这段代码,ttpfx的运行类型是Manager,而employee运行类型也为Manager。我们可以使用对象.getClass()来查看一个对象的实际运行类型,该方法就会返回实际类的全路径,上面代码输出如下

class com.ttpfx.Manager
class com.ttpfx.Manager

对象的运行类型和初始化有关,说白了就是new关键字后面的就是该对象的运行类型

强转类型转换

将一个类型强制转换成另外一个类型的过程称为强制类型转换。Java程序设计语言为强制类型转换提供了一种特殊的表示法。例如

		double x = 3.14;
		int a = (int) x

上面代码就将小数强制转换为了整数。
但是对于对象的强转有一点不同,我们只能将对象强转为对象的实际的运行类型或者对象运行类型的父类。

        Employee[] employees = new Employee[2];
        employees[0] = new Employee("tom", 10000);
        employees[1] = new Manager("ttpfx", 12000);

看上面代码,我创建了一个Employee的数组,数组第二个元素是Manager,可以发现我现在并没有设置Manager的bonus(奖金),但是现在出现了一个问题,employee[1]的编译类型是Employee,并没有setBonus()方法,于是我们就需要将employee强转为Manager,下面代码就将设置Manager的bonus

        ((Manager) employees[1]).setBonus(60000);

对于一个类型能否成功进行转换可以使用instanceof进行判断

        if (employees[1] instanceof Manager) {
            ((Manager) employees[1]).setBonus(60000);
        }

如果可以转换返回true,否则返回false。其实就是判断是不是某个类或者某个对象的子类

动态绑定

以上面的代码为基础,编写以下代码

    @Test
    public void t2() {
        Employee[] employees = new Employee[2];
        employees[0] = new Employee("tom", 10000);
        employees[1] = new Manager("ttpfx", 12000);
        ((Manager) employees[1]).setBonus(60000);
        for (Employee employee : employees) {
            System.out.println(employee.getSalary());
        }
    }

可以发现,我们使用foreach循环输出了数组内所有员工的薪水,在理想情况下,employee[0]应该输出10000,而employee[1]应该输出72000才正确,下面来查看一下。代码输出如下

10000.0
72000.0

可以发现也确实是这样的。这其实就是动态绑定,employee在调用getSalary方法时知道当前employee的实际运行类型,然后会在该类里面寻找getSalary,找到就直接调用,如果找不到那么再去父类进行寻找。因为employee[1]的实际运行类型是Manager,里面有getSalary方法,会返回salary+bonus的和,所以就不会调用父类(Employee)的getSalary方法了。

总结

其实上面这些东西说白了都是一个东西,就是对象调用方法会根据实际运行类型来开始查找方法进行调用,找不到再去父类查找。父类可以引用子类对象,我们只能将对象强转为对象的实际的运行类型或者对象运行类型的父类。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/140203.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!