两个java命令和一道看起来比较简单的面试题

LogicAetherMaster
• 阅读 1155
本来这篇文章是在我的另一篇算法文章之后才发布的,但是那篇文章一直卡在一个点上,卡了两个星期,按照我的规划来说,一周是要写两篇,所以只好先完成这一篇。

(1)

两个java命令和一道看起来比较简单的面试题

我们知道在java中用==进行比较的时候,比较的是内存中的地址. 对于非new 方式产生的字符串,在字符串常量池中。而字符串常量池位于方法区(也称永久代),在jdk1.7以下是跟堆隔离的。非new方式产生的字符串在进入字符串常量池之前会检查字符串常量池中是否已经存在该字符串了,如果有就不再重复的产生。比如你你用非new方式产生两个"helloworld", 用a和b分别指向他们,用= = 去比较,那么结果是true。

两个java命令和一道看起来比较简单的面试题

那请问图(1)怎么解释呢? e不是也是非new方式产生的吗? 那么比较结果为什么还是false? 答案就是e 是new方式产生的。这个时候可能有同学会说,你是不是以为我瞎啊! 明明就是非new方式产生的好吗? 那么请先不要着急,请听我细细道来。

很多时候,我们java程序员在优化自己的代码,其实编译器也在优化你的代码,你认为d + "world"的时候虚拟机在调用的是哪个方法进行拼接呢?我们知道java源代码由编译器变成字节码,在由源代码到字节码这个过程中,编译器做了大量的工作,相信各位在大学学过的编译原理的都知道。我们可以通过JVM提供的一些指令,来看清"字节码",就是虚拟机在执行这一行的时候,做了什么?

javap The Java Class File Disassembler
-c You use the javap command to disassemble one or more class files
-verbise: Prints stack size, number of locals and args for methods.

javap -c 就是反汇编字节码
javap -verbose 比-c更进一步打印出来栈打大小和方法参数

关于这个指令来说,有的人将其称为反编译,有的人称其为反汇编。
我们首先来解释反编译和反汇编的不同,在接着来说哪一个更译名更为合适。
反编译: 高级语言源程序经过编译变成可执行文件,反编译就是逆过程。
反汇编: 反汇编(Disassembly):把目标代码转为汇编代码的过程,也可以说是把机器语言转换为汇编语言代码
disassemble 和 disassembly,从这个角度上来讲,称呼这个指令为反编译更为贴切些。

那么java字节码可以称之为机器语言喽? 那什么叫机器语言呢? 能被计算机直接识别的编程语言吗? 这个定义还是很粗糙。

机器语言(machine language)是一种指令集的体系。这种指令集称为机器代码(machine code),是计算机的CPU可直接解读的数据。机器代码有时也被称为原生码(Native Code),这个名词比较强调某种编程语言或库与运行平台相关的部分。
机器语言是用二进制代码表示的、计算机能直接识别和执行的一种机器指令的集合。它是计算机的设计者通过计算机的硬件结构赋予计算机的操作功能。机器语言具有灵活、直接执行和速度快等特点。不同种类的计算机其机器语言是不兼容的,按某种计算机的机器指令编制的程序不能在另一种计算机上执行---维基百科

那什么叫指令集呢?

指令集架构(英语:Instruction Set Architecture,缩写为ISA),又称指令集或指令集体系,是计算机体系结构中与程序设计有关的部分,包含了基本数据类型,指令集,寄存器,寻址模式,存储体系,中断,异常处理以及外部I/O。指令集架构包含一系列的opcode即操作码(机器语言),以及由特定处理器执行的基本命令。---维基百科

那什么叫指令?

在计算机技术中,指令是由指令集架构定义的单个的CPU操作。在更广泛的意义上,“指令”可以是任何可执行程序的元素的表述,例如字节码。

讨论到这里,就有些收不住了。关于字节码和机器语言,有时间的话会专门写一篇文章.

我们姑且就称javap 为反汇编指令,它可以将字节码变成一种类似于汇编指令,汇编指令相对于机器语言就好懂的多了.
我们来解释图1,事实上,虚拟机在执行d+"helloworld"的时候,是调用了StringBuilder方法,然后在调用StringBuilder的toString方法返回给e,而StringBuilder的toString()方法,又是采用了new的方式

两个java命令和一道看起来比较简单的面试题

那么有什么证据呢?

两个java命令和一道看起来比较简单的面试题

相信各位大概都可以看懂了,这是反汇编图(1)的字节码的产物

如果程序变成下面这样呢?

两个java命令和一道看起来比较简单的面试题

此时的运行结果为true,我们再次反汇编其字节码。来看看仅仅是加了一个final关键字,字节码发生了什么变化?

两个java命令和一道看起来比较简单的面试题

我们发现在第六行e就已经变成helloworld了,这个时候就没有再调用StringBuilder,仍然是非new方式产生的。
那这是为什么呢?

这就是编译器的常量折叠技术,非java所独有。对于一些表达式符合语言中所定义的常量条件,那么这些表达式在编译器就会被编译器进行计算,而不会等到运行时在进行计算。

那么javap还可以帮我们解糖,在java中存在着相当一部分的语法糖。

语法糖: 语法糖(Syntactic sugar)是由英国计算机科学家彼得·兰丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性

举例: 注解并非是一种新的数据类型,而是一种特殊的接口。不信的话,我们反汇编一下注解,就可以看明白我说的

两个java命令和一道看起来比较简单的面试题

反汇编后的结果:

两个java命令和一道看起来比较简单的面试题

那synchronized呢? 这个在分解为什么了呢?
对于静态方法和非静态方法还是有点小不同的,以后会专门写一篇文章来介绍。
某些情况下,用反汇编指令我们可以清楚的看到,for和foreach是一回事
for和foreach又有一些不同。

在IDEA中可以直接配置javap -c 和 javap -verbose这两个指令,这样就不用每次就用CMD方式了,方便快捷。如何配置,网上有很清晰的教程,这里我就不介绍了。

点赞
收藏
评论区
推荐文章
Karen110 Karen110
4年前
小红书很难爬?最新爬取方法教给你啦~
Python进击者第184篇原创文章前言大家好,我是Kuls。之前写的那篇App抓包软件charles的配置说过,超过30在看,马上更下一篇。所以加班加点给大家写了今天这篇文章。本文将会带着大家完完整整的爬取小红书的全过程小红书需要做的前提工作就是装配好mitmproxy具体的配置过程,我建议大家参照崔大写的来进行安装https://zhuanlan.z
blueju blueju
4年前
umi + qiankun 动态注册子应用解决方案
前言首发于<br/本篇文章可以被视为上一篇文章()的延续,上一篇文章大致讲述了搭建一个简易微前端平台的过程,其中关于子应用注册的配置是通过硬编码的方式,在构建打包前写入的。<br/<br/但是真实项目中,更需要的是动态注册子应用,比如说我正参与的这个项目。<br/<br/本篇文章的示例代码是基于上一篇文章示例代码改动的,上一篇文
Jacquelyn38 Jacquelyn38
4年前
我熬夜开发了一款简约实用、支持多平台的Markdown在线编辑器(开源)
前言之前,一直想开发一款属于自己的Markdown编辑器,主要是自己平常写文章可以更加灵活操作,另外扩宽自己的视野也是非常不错的选择啊!所以在周末就决定玩耍一番。首先我调研了很多线上热门的md编辑器,都很优秀。不为超过他们,主要自己用着舒服点。这篇文章主要是记录下我是如何从0到1是完成一款还算拿得出手的Markdown编辑器。完成项目一览调研Markdown
灯灯灯灯 灯灯灯灯
4年前
面试百度和美团,竟然问我多线程安全问题,正好撞在我知识点上
解决多线程安全问题无非两个方法synchronized和lock具体原理以及如何获取锁AQS算法本篇文章主要讲了lock的原理就是AQS算法,还有个姊妹篇讲解synchronized的实现原理也是阿里经常问的,一定要看后面的文章,先说结论:非公平锁tryAcquire的流程是:检查state字段,若为0,表示锁未被占用,那么尝试占用,若不为0,检查
Stella981 Stella981
4年前
Linus,一生只为寻找欢笑(完全版)
文章来源:池建强  微信:MacTalk!(http://static.oschina.net/uploads/space/2016/0417/074758_oIWK_1774694.jpg)这篇文章我在2013年2014年分十次左右完成的,记录了Linux作者Linus的故事,算是我写的最好的一篇长文。这篇文章分别发表在我自己的书《
Wesley13 Wesley13
4年前
IDEA 终于支持中文版和 JDK 直接下载了(太方便了)附新版介绍视频
!(https://oscimg.oschina.net/oscnet/8db621b0f5dad6210c42645dd5fd84172ce.png)这是我的第48篇原创文章。IDEA2020.1经过了漫长的打磨终于发布正式版了,而这次的版本不止直接支持Java14,还带来了两个重量级的功能:官方中文版支持和JDK直
Stella981 Stella981
4年前
Foreground
10个月前,我写了一篇解读欧拉影像放大技术的文章EulerianVideoMagnification,这篇文章自发布以来,点击率超过了1300次,评论数达到了29篇。如果你在baidu上搜索“EulerianVideoMagnification”,我的文章排在第二名(第一名是原论文的链接)。而如果你在google或baidu上搜索“欧
Wesley13 Wesley13
4年前
ActiveMQ
1前言前一篇介绍了JMS有两种通信模型,一种是点对点通信,另一种是发布/订阅模型,本篇将会继续探讨这两种模型。本篇文章需要按照严谨的实验顺序才能获得相同的结果,这是因为消息持久化和持久订阅这两个特性的原因,在文章结尾和下一篇文章会做解答。\\所有的实验在启动之前都必须到管理后台删除相关的队列或者topic,否则数据也可能不同\\在A
Wesley13 Wesley13
4年前
Java内嵌Groovy脚本引擎进行业务规则剥离(四)
前三篇文章已从groovy脚本的基本使用到java解析,json对象结合作了一基础铺垫。这篇文章是本系列的最后一篇文章。在第二篇文章中,说到用groovy编写的规则脚本,然后采用文件字符串的形式加载到java中,解析并运行。在我的应用场景中,每一条规则就是一个业务指标项。每一个指标项能够单独维护,而不是把所有指标项统一放到一个文件中。那么,我需
Python进阶者 Python进阶者
2年前
盘点一个Pandas取值的问题(下篇)
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据提取的问题,上一篇文章我们介绍了基础篇,这一篇文章我们来延伸下,你想象下,我想要14和15行该怎么写?二、实现过程后来【论草莓如何成为冻干莓】给了一份代码,pri
深入理解经典红黑树 | 京东物流技术团队
本篇我们讲红黑树的经典实现,Java中对红黑树的实现便采用的是经典红黑树。前一篇文章我们介绍过左倾红黑树,它相对来说比较简单,需要大家看完上篇再来看这一篇,因为旋转等基础知识不会再本篇文章中赘述。本篇的大部分内容参考《算法导论》和Java实现红黑树的源码,