00:00
那这一节啊,咱们先给大家讲一讲,叫字符串的一个拼接操作,那前面这三节啊,讲完以后,那有些有开发经验的同学呢,可能会说是这个宋老师前面你讲的这三小节啊,有点简单是吧,或者说就没有必要去讲了啊可以呢,这样理解,咱们前面三小节啊是作为一个铺垫,或者说呢,就大家吃饭之前的一个开胃的小点心啊,感受一下这个都很清楚了是吧,那么咱们这个第四节包括呢,咱们下边要讲这个第五节里边呢,蕴含了很多的一个知识,那这里边呢,大家开发中是不一定清楚的,那如果说在面试当中问到这些问题呢,那相对来说也是比较高级的。或者说呢,诶咱把这事儿呢讲透以后,那我觉得大家诶,如果面试中问到这样的问题,你呢,甚至也可以诶跟面试官做进一步的交流,哎我只的进一步交流呢,实际上你是具有这个反问他的能力的,但是呢,你们也必要把这个面试呢整的这么尴尬是吧?哎你最后呢,把面试官给虐了,然后呢,这个呃态度呢,再加上要不太友好的话呢,可能面试官呢,呃心里边一横,还不愿意要你的是吧?呃就这里边你要知道就是咱们呢,是可以把这个问题呢谈的是比较清晰透彻的,好,那咱们呢,先来看这个第四节,叫做字符串的一个拼接操作先呢,咱们把这个结论呢给大家说出来。
01:16
好,大家看一下,第一个说呢,常量与常量的拼接,这个拼接啊,就是咱们以前讲Java运算符的时候呢,这个叫连接符,这呢就成为一个叫拼接了,说常量与常量的拼接呢,结果呢是放在常量池当中的。那这里边使用的原理呢,叫做编译器优化,哎,叫编译器优化,一会儿咱们直接上代码,常量池当中是不允许存放相同内容的常量的,这个咱们前边呢,翻来覆去的说这个点,大家一定要记住它。下一个说,只要其中有一个是变量,就是我们所谓这个拼接操作啊,前边后边不就是两个位置吗?那这两个位置当中,只要你有一个位置是变量的话呢,这个结果呢,就得是在堆当中,当然这个呢,咱不是特别明确了,为啥呢?因为一个叫堆,一个叫常量池,常量池本来也在堆是吧,那这个呢,咱们尺的堆呢,不是常量池的那个区域。
02:06
也就是说呢,比如说这是堆空间,这呢是堆空间中的常量池,咱们这里说的这个堆呢,是剩下这个空间,就类似于我们六个对象你就放在这个位置一样。是在这个堆里边,它的这个原理呢,是string builder。哎,叫string builder,好,那接着咱们往下说,一会呢,代表演示说,如果拼接的结果呢,诶这个又调用一个叫做inter方法,则主动呢将常量池当中还没有的这个字符串对象呢放到池当中,并呢返回此对象的地址。这个前提是我们这个常量池当中,也就是说字符串常量池当中,那目前呢,没有这个字符串,我们呢,就给它放一个,那如果说你要已经有了呢,你要已经有的话呢,我就把你有的这个对象的这个咱们也叫对象了,就是你字符串常量池里边那个字符串常量,把它的地址呢返回。关于这个int的话呢,咱们下边还有进一步的说明,所以这个呢,咱们通过代码呢,给大家展示一下就清楚了,好,下边呢,咱们直接呢来上这个代码,这个代码的话呢,咱们就来看一下。
03:06
这呢叫string test5就是这个代码,这个代码里边咱们写了好几个例子,其中呢有很多其实都是这个面试当中或者是笔试当中的一个题目,咱们呢把它弄清楚,弄透彻好,咱们一个一个来逐步深入,首先呢来看第一个问题,现在咱们整一个这个柔和一点的,我这呢声明了两个字符串,嗯,A连接B连接C,这呢是叫ABC。那么现在问的就是说这个S1和S2,如果我用等等和equals呢去比较看看结果呢是出还是false,那很显然呢,这S1EQUALS s2的时候呢,这个结果呢,是不是一定大家所有的人100%都应该知道是出对吧?这个你写成错的话呢,这你的智商呢,这就就麻烦了啊,肯定是看花眼了啊,这个用ECO的比的话呢,显然呢都是ABC,那绝对是true,关键的就是我们看SSAS2呢,它俩的地址是不是一样子的,咱们说这个引用类型的变量,这个等等呢,判断就是他们二者的地址了。
04:00
那这呢是我们毕竟比较关心的,那比较清晰的就是咱们这个S2,这呢是不是使用自变量的方式进行的一个赋值,那此时的我们说这个ABC它呢,是不是一定。这个是放在字符串常量池中的。而且呢,咱们S2呢,里边记录的就是你常量池里边这个ABC它的一个地址,对吧,它呢,一定是放在自串常量池中,然后呢,将此地址。嗯,地值这个付给咱们的S2 OK,那么现在的问题呢,就归结在咱们S1的ABC,它呢,是不是也是用的常量池里边那个ABC。那答案呢,是是的是吧,我们这就是出从两个角度呢,我们带着大家看一下,你看我这其实也写了咱们这个程序的话呢,首先做一个编译,编译完以后咱们就会生成资金码文件,那么这个资金码文件在咱们idea当中啊,它直接呢,是可以给我们做一个反编译的,所以咱们直接在这块,嗯,往下走找到我们这个第13章啊,往下找咱们是在这里边是不是有一个这个五是吧,把它直接打开这块,你看到实际上是反面以后的这个结果啊,这个刷新一下,好,那我们来看一下这个T子一,在这里边大家明显能看到我们这个SSE呢,是不是就写成ABC啊。
05:21
跟我们这S2呢写法一样,这呢是咱们把这个自节码文件呢,给它做了一个反编译之后呢,咱看到的这样的一个场景,那这个场景呢,显然跟我们刚才这呢是不太一样的,那通过这个呢,咱们说明的就是刚才的第一个结论说呢,你要是常量跟常量的拼接呢,这个就是在常量池里的。它呢就是编译器优化,就是在我们生成资金码文件的时候呢,就直接呢,将你这个操作呢,就理解为或者呢,就是等同于ABC,那接着的话呢,他们二者呢,实际上呢,这时候是首先在常量池里边放了个ABC,这块呢,就没有再放,而是使用了已有的这个ABC了。对吧,那所以呢,这个时候呢,它这个结果呢,也就是个除跑一下。
06:04
没问题对吧,两个都是出行这呢,是我们通过这个idea这样的一个特殊的一个场景,就是直接呢,他给我们做了一个反编译看到的一个情况,那还可以怎么看呢?咱们回过来看一下这个Java文件,那我们把当前这个进行反编以后呢,咱还可以看一下这个j class lab,在这个接class lab里边刷新一下,首先呢,我们看下这个T一看下这code,大家在这呢,实际上也能够看的比较清晰,来看一下在我们这个TEST1里边,它这呢,你看上来是不是就我们LDC就是从自符串常量池里边做了一个加载,加载了一个ABC,相当于呢,我们常量池里边就放了一个叫ABC,把它呢保存在咱们这个局物变量表一的这个位置上。那零的位置的话呢,我们知道还是这个是不是Z4啊,然我们看这个局部变量表零的话还是Z4对吧?然后这个一的位置呢,放的是S1,然后二的位置上放这S2行回过来,那把我们这个ABC呢,就放在这个一的位置上了,相当于我们这S1呢,就是常量池里边这个ABC,嗯,然后再往下的话,你看是不是又是常量池,这ABC放到这个叫S2的这个位置,这这个这个旧变量表索引二的位置其实就是我们S2,那他俩你看都是拿的常量池里的,显然呢,是不是地址就一样的。
07:15
很非常的清晰,OK,说透彻了下一个问题,看着这道问题的话呢,在面试当中应该算是比较难的一个问题了。我们看一看,我这呢,造了两个字符串,扎一汉突破。然后S3的话呢,是这样的,S4这样,S5这样,主要的区别就是我们现在呢,出现了拼接的时候呢,前后有变量的场景。前后有变量的场景,行,那大家呢,咱们一起来做一做,看看你呢,是不是能够把这个呢填写的正确,首先三跟四有了我们刚才这样的一个底子的话呢,是不是显然它是一个出啊。这里边呢,咱们全是这个判断,等等就不写ecoose了啊,要写ECO的话呢,是不是有点侮辱你智商啊啊这咱们就等等啊,这个三跟五三是在这五在这这个呢,结果是不是应该叫false。
08:02
然后三跟六,三是这六是这儿还是false。咱们呢,等于来解释这个三跟七,三在这儿,七在这儿还是负。那这都是false,那么这个567 567,它们三者之间用等等判断的话呢,会是处吗?那么很遗憾呢,他们也是false。这个567他们彼此之间呢,都不是同一个地址。所以呢,全是for。没问题,这样子,这样你看一共几个,1234566个是吧,这出,然后在下边呢,S6.inter方法,当我们调离inter方法的时候呢,返回的这个S8 S8跟S3什么关系啊,这是一个处。下边呢,咱们就来解释一下,先跑一下看看这个咱们刚才写这个答案呢,对不对。出来了行,那一开始呢,是一个处,中间呢有六个false,出1234566个false,然后最后的话呢,又是个出,嗯,OK,对的。
09:06
先看一看,大家呢,你在我们讲这个知识之前呢,你能不能把这个知识点呢,先梳理清楚。看能不能先梳理清楚,下边呢,咱们就相当于你要是解释的话呢,就得具体来说了,对吧,其实要具体说的话呢,就是咱们下边这个场景了。就是下边这个场景,你看我这呢,是不是就是相应的一些运算是吧?行这块呢,就大家先会做这道题啊,咱们呢,哎想先说的这个结论呢,是这样子的,就是只要呢,你这个拼接的时候呢,有一个呢是变量,那这个结果呢,就是在堆当中。就是在堆当中,相当于呢,我们是这个新new了一个对象,那所以说呢,这个三跟四的咱不用多说,他俩呢是一个事儿,咱们如果还是看这个资金码文件这个再刷新一下的话呢,你看我们这个三跟四,你看三跟四是不是都是对的,都是都是完全写成一样的了,这上就是我们说的叫诶编译器的优化。编译起来一句话,上面这个呢也是一样。
10:01
嗯,这也是一个编译器优化。OK,那么如果说呢,你这个拼接的前后字符串呢,出现了变量,那么出现变量的话呢,这个时候我们要强调一下,在这我直接来写了。如果拼接的。拼接符号或者叫连接符号的这个前后。出现了变量。哎,则需要呢,在堆空间中。嗯,堆空间中啊去拗这个,嗯,其实我这块我就直接说咱们下边呢,是说这个具体的细节啊,则需要或者叫则相当于吧,在对空间当中啊又一个词缀,那具体的内容就是我们这个字符串内容为这个拼接以后的结果。
11:01
咱们一点点展开,那拼列结果是什么呢?就比如说咱们下边这个S5S6S7,他们的结果呢,是不是都叫JAVA1很多啊。这呢是它这个拼接的结果,那么每一个只要你前后出现了这个叫变量了,那都相当于是扭,那就是这扭了个对象啊,这扭个对象,这扭了个对象,那扭了三个对象,那三个对象呢,显然我们说只要你new的话呢,就是一个新对象,开辟了一个新空间,那就是一个新的引用地址,所以呢,他们都是false啊,记住这个事。行,那接着往下看,那我们此时呢,调了这个叫in方法,那注意咱们这个in方法它呢意思是什么?咱们下一节当中重点讲的是它啊,咱们这块呢,就先引入一下,因为在面试的时候呢,可能就出这道题里边就有这个in特了,这个in特的话呢,就是咱们需要呢,把这个S6呢,它对应的这个字符串这个值咱们这里边呢,都知道是JAVA1函do,就是这个值的话呢,把它呢,诶在字符串常量池里边做了个校验,如果说常量池里边没有这个张阿一函杜呢,我们就创建一个,如果要有的话呢,把字符串常量池里边有的那个张阿姨韩渡河这个字符串的地址做一个返回。
12:11
哎,我在这稍微写一写啊,CTRLC一下,那此时的话呢,就是哎,判断字符串常量池中是否存在,我就直接写了这个值,那说如果要是存在。那如果要是存在啊,则返回常量池中。嗯,则返回常量池当中这个字符串它的一个地址。这是说如果你要是在的话,好接着。说诶这个啊,说如果字符串常量池。不存在。如果不存在咱们这个字符串的话呢,则嗯,在常量池中。
13:05
加载一份。嗯,加载一份呢,咱们这个字符串,然后呢,并返回此这个,诶对象的地址。OK,就是这样的一个过程,行,那么很显然呢,咱们当前这个S6对应的呢,这它的这个具体内容叫张二一很多破了,咱们前面呢,是不是一上来S3的时候,诶对,一上来S3的时候呢,我们在长远池里边就放了一份,这个呢是首次往里边放。嗯,那既然你常量池里边有了,那我就把你Z串常量池已经有的那个张阿姨喊多文那个地址呢,返回给了S8,那显然呢,S8跟我们一开始的这个S3它的地值呢,是不是就一样的呀,所以这个呢,就是个处。没问题行,那这呢,就是我们针对面试当中呢,大家问的这两个问题呢,咱们先做一个说明,然后下边呢,咱们把这个啊,就是拼接的时候呢,它的这个底层细节啊,咱们通过自解码的方式呢,来看一看。
我来说两句