Java中的this关键字。this究竟指谁?this对比super。从this出发理解Java中的方法调用! |
您所在的位置:网站首页 › 欧楷指的是谁的字 › Java中的this关键字。this究竟指谁?this对比super。从this出发理解Java中的方法调用! |
文章目录
引出问题解决问题this和super理解方法调用重载中的方法匹配继承关系中的方法匹配
引出问题
现在有两个类Employee类和Manager类 这两个类的关系为:Manager extends Employee Employee类中有name,salary,hireDay字段。Manager类中只比Employee类中多出一个bonus字段。重点关注代码中的equals方法和构造方法 Employee类 import java.time.LocalDate; import java.util.Objects; public class Employee { private String name; private double salary; private LocalDate hireDay; //...省略掉了get set方法 public Employee() { } public Employee(String name, double salary, int year, int month, int day) { this.name = name; this.salary = salary; hireDay = LocalDate.of(year,month,day); } @Override public boolean equals(Object otherObject) { if (this == otherObject) { return true; } if (otherObject == null) { return false; } if (this.getClass() != otherObject.getClass()) { return false; } var employee = (Employee) otherObject; return Double.compare(employee.salary, salary) == 0 && Objects.equals(name, employee.name) && Objects.equals(hireDay, employee.hireDay); } }Manager类 import java.time.LocalDate; import java.util.Objects; import java.util.SplittableRandom; public class Manager extends Employee { private double bonus; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); bonus = 0; } @Override public boolean equals(Object otherObject) { if (!super.equals(otherObject)) { return false; } Manager manager = (Manager) otherObject; return Double.compare(manager.bonus, bonus) == 0; } } 解决问题问题来了! 我在main方法中新建了两个Manager的对象,boss1和boss2,并调用了equals方法比较这两个对象是否相等。 但是在Manager类的equals方法中又调用了父类的equals方法 又来看看Manager的父类Employee中的equals方法 在Manager的父类Employee类的equals方法中,我们使用了this。 问题:在调用equals方法的时候,这里的this是指Employee类型的引用吗? 我们很清楚,我们是这么调用方法的boss1.equals(boss2)。boss1和boss2都是Manager的对象。那Employee类中的this指的是Employee类型的引用还是指Manager类型的引用?。 调试一下便知道了: 在main方法中的boss1的引用的id为825 在Employee类中的this引用的id也是825 id相同,也就说明这两个引用是同一个引用。 真相大白了。Employee类中的this是boss1这个引用。 也就是说。某个类的this指的并不一定是这个类所对应的引用,而是指实际调用this对应的方法的引用。谁调用了this对应的方法,this就指谁。简而言之:this是谁并不取决this是在哪个类里,而是取决于是谁使用了这个this。 this和superthis和super本质上并不是一个东西。this的本质上是一个引用,而super本质上只是一个关键字。比如:super.equals(otherObject)是在指示编译器在这个地方要调用父类的equals方法,而不是当前类的equals方法。虽然这样看起来好像是使用一个对象,然后通过.操作符来调用方法,实则并不是。 比如下面的例子:this本质上是一个引用,所以可以赋值给其它引用。但是super本质上并不是一个引用,如果像如下那样赋值则会发生错误。 Employee employee = super; //错误 Employee employee = this; //正确 理解方法调用从上面的this的那个例子,应该可以隐约感受到Java执行过程是一个动态决策的过程。变量声明的时候是什么类型,不代表最终就调用该类型的变量所对应的方法。变量声明的时候是什么类型,不代表最终执行的时候变量就是这个类型。 重载中的方法匹配如下,调用buy(money)的时候究竟会调用以下哪个方法? public static void main(String[] args) { float money = 2.f; buy(money); } public static void buy(int money) { //... } public static void buy(double money) { //... } public static void buy(short money) { //... }最终是会执行buy(double money)这个方法。传入参数的时候传入的是float类型的参数,实际的方法中并没有对应着参数为float类型的buy方法。怎么办呢?这个时候,编译器就开始进行类型转换,类型转换是向着更高精度的类型来转换。没有float类型的,那么就去看看有没有参数为double类型的方法,声明的方法中有参数为double类型的方法,因此匹配成功开始执行。 Java匹配参数匹配的顺序为:byte -> short -> int -> long -> float -> double。 如果没有参数为float,也没有参数为double类型的buy方法,则无法进行匹配,最终会报错。 继承关系中的方法匹配假如有这么几个类A,B,C。他们的关系如下: C extends B, B extends A。 首先:假设A,B,C类中都有一个f(String str)方法。 A a = new C(); a.f("hello");问题:按照上面那样进行调用,最终究竟是调用A类中的f(String str)方法,还是调用C类中的f(String str)方法?。 答:会调用C类中的f(String str)方法。 调用哪个方法,不是看引用的类型,而是看这个引用实际指向的对象的类型。 从Java10开始,定义变量的时候我们可以不用指定变量的类型,直接使用var关键字来声明。比如var a = new C(); 为什么要这么做呢?因为实际调用哪个方法,并不是由变量类型来进行决定的,而是由Java在执行的过程中动态决定的,因此声明变量的时候,指不指定类型就显得无关紧要了。 还是按照上面那么调用。但是现在C类中若没有声明f(String str)这个方法。那a.f("hello");会调用哪个类的方法? 答:如果C类中没有f(String str)方法,就会去找C类的父类—B类,如果B类中有f(String str)方法,则进行调用,没有则顺着这条继承链,继续往上找,如果找到方法签名与f(String str)的方法签名相同的方法,就开始执行,找不到则报错。 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |