知道的越多,不知道的就越多,业余的像一棵小草!

编辑:业余草

来源:https://www.xttblog.com/?p=5028

B 站:业余草

最近一个粉丝加我说,接到了阿里的面试,问问我阿里会面试哪方面的东西。我说,阿里的套路基本上是,你会什么就问你什么,直到问得你怀疑人生。正所谓,你知道的越多,不知道的就越多,业余的像一颗小草!

今天,我们就一起来讨论一个这个网友遇到的阿里面试题,Java 中 this 和 super 关键字的底层实现原理!文章后面附了一个我录制的视频,大家忽略!

众所周知,在 Java 中,this 具有以下含义。

  • 在 Java 中,每当一个对象创建后,Java 虚拟机都会给这个对象分配一个指向自身的引用,也就是 this。同时如果对象是子类对象,则还会有一个 super 引用指向当前对象的父类对象。
  • 在类的方法定义中使用 this 关键字,表示使用该方法的对象的引用。
  • 在一个类中,this 可以表示该类的当前实例。
  • this 是对当前类对象的引用,对象只有被实例化才存在。

根据 this 的这些含义,面试官就想知道 this 是怎么出来的?先看下面的代码。

public class Xttblog {    private String name;

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

    public static void main(String[] args) {        Xttblog xttblog = new Xttblog();        xttblog.setName("业余草");    }}

在 setName 方法中,可以使用 this 的本质是:编译器在调用某个实例方法时,实际上会把当前的实例对象的引用作为第一个参数传递给方法。

经过编译器的处理,xttblog.setName(“业余草”) 这行代码实际上变成 xttblog.setName(xttblog,”业余草”)。而如果想从方法内部获取当前对象的引用,就有一个专门的关键字 this,表示“调用方法的那个对象”的引用(如 xttblog)。

这一点,我能想到有 3 种方法来验证它。

第一种是我们通过 Bytecode 工具查看字节码的时候,会发现有 setName 方法有两个 LOCALVARIABLE,即两个局部变量,一个是 String 的,一个是 Xttblog 对象。

OCALVARIABLE args [Ljava/lang/String; L0 L3 0LOCALVARIABLE xttblog Lcom/xttblog/Xttblog; L1 L3 1

第二种就更简单了,我们给 setName 方法在第一位再加一个 Xttblog this 参数,你会发现编译器不会报错,方法调用都能够成功。

public class Xttblog {    private String name;

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

    public static void main(String[] args) {        Xttblog xttblog = new Xttblog();        xttblog.setName("业余草");    }}

第三种验证方法,我们借助 Java8 提供的函数接口来验证。比如下面的代码。

public class Xttblog {    private String name = "业余草";    private String sayStr;

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

    private String say(String sayStr){        this.sayStr = sayStr;        return this.name + " say : " + this.sayStr;    }

    public static void main(String[] args) {        Xttblog xttblog = new Xttblog();        xttblog.setName("业余草");

        BiFunction function = Xttblog::say;        String str = function.apply(xttblog, "hello~");        System.out.println(str);    }}

以 BiFunction 为例,它要求的是以两个输入参数,一个输出参数。而我们调用的 say 只需要一个字符串类型的输入参数,但是我们的示例代码中,却传递了两个参数。一个是 Xttblog 类型,一个是 String 类型,编译器没有报错,可以正常执行。

这也验证了 this 的底层实现原理。

同理,super 的本质是:当我们 new 一个子类对象的时候,子类除了生成一个 this 引用指向自身,还会生成一个指向其直接父类对象的引用 super。如果子类在继承父类的非私有的法和成员变量时,没有同名的方法和变量,可以直接通过名称使用父类的方法和变量。如果子类存在与父类同名的方法和成员变量时,要想区别访问父类和自身的变量和方法,需要使用 super 关键字调用父类的方法和属性。

这些在字节码中都有体现。以下面的代码为例:

public class Codedq extends Xttblog{    private String skill;

    public void setSkill(String skill){        this.skill = skill;        System.out.println(super.say("hello world"));        System.out.println(super.getName() + "会:" + this.skill);    }}

我们在字节码中会看到,在 Codedq 的构造函数中,调用了父类 init 方法。

public ()V   L0    LINENUMBER 9 L0    ALOAD 0    INVOKESPECIAL com/xttblog/Xttblog. ()V    RETURN   L1    LOCALVARIABLE this Lcom/xttblog/Codedq; L0 L1 0    MAXSTACK = 1    MAXLOCALS = 1

注意上面的 INVOKESPECIAL 指令。super 关键字的底层原理就是靠 INVOKESPECIAL 指令。

在 Codedq 的代码中,super 就是靠 INVOKESPECIAL 指令来调用父类方法的。

invokespecial 指令的主要作用是,用于调用一些需要特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法。(Invoke instance method; special handling for superclass, private, and instance initialization method invocations )。

最后,我们来个简单的总结,this 的底层实现是默认传值,super 是靠 INVOKESPECIAL 指令

以上内容,若有疑问,欢迎公众号评论区留言指正!


java底层原理书籍_阿里面试题:Java中this和super关键字的底层实现原理相关推荐

  1. java面试逻辑思维题目_逻辑思维面试题-java后端面试

    第一题 4 2 12 28 80 写出后面那个数 A.124 B.96 C.216 D.348 正解C 28=(12+2)*2 80=(12+28)*2 216=(80+28)*2 第二题 A,B,C ...

  2. java书籍_还搞不定Java多线程和并发编程面试题?你可能需要这一份书单!

    点击蓝色"程序员书单"关注我哟 加个"星标",每天带你读好书! ​ 在介绍本书单之前,我想先问一下各位读者,你们之前对于Java并发编程的了解有多少呢.经过了1 ...

  3. java必读书籍_最佳5本Java性能调优书籍–精选,必读

    java必读书籍 为什么Java开发人员应该阅读有关性能调优的书? 当我很久以前第一次面对这个问题时,我以为以后会做,但是我很长一段时间都没有回过头来. 仅当我在用Java编写的任务关键型服务器端财务 ...

  4. java在线编程题_阿里笔试题(2017在线编程题)-- 数串分组 --Java实现

    看到有人写了阿里的面试题,心里痒痒,好久 没搞过这些了,写着实现一下 题目 2017年3月阿里在线编程题(实习内推) 给定一串数字 判断是否存在这三个元素,它们将数字串分为四个子串,其中每个子串的数字 ...

  5. java下拉菜单_薪资对比:Java开发和web前端薪资哪个好

    Web前端开发和Java开发哪个薪资更高,Web前端开发和Java开发发展前景更好? 互联网行业飞速发展,因此有很多小伙伴想要进入IT行业分一杯羹,但是学什么技术更好,哪一个语言的就业薪资更高,就成了 ...

  6. java编写布局文件_鸿蒙OS利用JAVA编写的布局实践练习

    鸿蒙OS利用JAVA编写的布局实践练习 鸿蒙OS利用JAVA编写的布局实践练习 目录 JAVA UI框架 利用JAVA代码实现一个简单的布局 利用xml实现上述布局 JAVA UI框架 ??应用的Ab ...

  7. java 字节码查看_一种查看java字节码时显示方法调用关系图的方法与流程

    本发明涉及一种代码逻辑分析方法,具体涉及一种查看java字节码时显示方法调用关系图的方法. 背景技术: 目前软件反编译领域有不少对可执行文件进行反编译的工具如IDA,也有对Java代码生成的中间码文件 ...

  8. java 并发 调优_阅读笔记一——java高并发的性能优化

    前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没 ...

  9. java语言程序设计考点_计算机二级考试Java语言程序设计考点:关键字

    大家回忆一下我们在学习汉语的时候,开始学的是什么?肯定是先学一些单个的字,只有认识了单个的字,然后才能组成词,然后才能慢慢的到句子,然后到文章.学习同计算机交流跟这个过程是一样的,首先我们得学习一些计 ...

最新文章

  1. 数据蒋堂 | SQL是描述性语言?
  2. TorchScript的简介以及项目踩坑
  3. 菜鸟做设计必看!有关如何做设计的整体思路,以及能否综合的笔记
  4. 太强了!机器视觉相机解决硬币制造难题!
  5. 10.28T5 tarjan+dfs
  6. 安装windows时loading files结束就重启_软网推荐:不用制作系统盘 也能安装新系统...
  7. 使用Palette来对图片进行颜色提取
  8. 题目399-整除个数(满满的套路)
  9. matlab分析启动子特征,文献编译 | 相对脑血容量(rCBV)可作为MGMT启动子甲基化阳性GBM的辅助预后指标...
  10. 信鸽推送集成采坑之代码混淆报错/XINGE: [Util] please add wup-1.0.0.E-SNAPSHOT.jar in your libs
  11. 浅谈 “ 站内信 ” 的实现
  12. 使用360优化修复系统后无法上网的解决方法
  13. linux查看源码工具,快速查看Linux系统工具的源代码
  14. 麦克利兰的成就动机理论(1966)--zz
  15. Docker存储空间清理方法
  16. rabb.it和uzer.me 两个在线观看 youtube / goolge在协同办公平台
  17. [AHK]让当前脚本开机自动启动
  18. 有关微软安全漏洞及补丁(HotFix)的命名规则
  19. 税务服务器管理系统登不上,网上税务局登录失败解决方案
  20. Java枚举类型与泛型

热门文章

  1. php将文件夹打包zip文件,php将文件夹打包成zip文件
  2. STM32 之八 在线升级(IAP)超详细图解 及 需要注意的问题解决
  3. 算法练习day13——190401(前缀树、贪心策略拼接字符串使字典序最小)
  4. 用yacc编写的算术运算计算器_Linux里隐藏的计算器,你知道它的奥秘吗?
  5. C/Cpp / 虚函数是否可用 static 修饰
  6. 进程有一个全局变量 i,还有有两个线程。i++ 在两个线程里边分别执行 100 次,能得到的最大值和最小值分别是多少?
  7. Linux / 守护进程
  8. java 内存空间_怎样用java实现存储空间动态分配
  9. 创建一个html网页,创建第一个HTML网页(未完待续)
  10. 【51nod2026】Gcd and Lcm(杜教筛)