00:00
行,那关于in特呢,比较难的这道面试题啊,包括它的变形咱们就告一段落,那课后的话呢,咱们也又多加了两个练习,那通过这两个练习呢,当中咱们也涉及到了我们去new string这样的方式呢,创建对象,底层呢到底造了几个对象,那以及的话呢,它的一个拓展就是new string,再去拼接上一个new string,它的底层又创建过几个对象,那彻底呢,咱们就算是解释清楚了啊包括包括这个in特呢,咱们也这个比较透彻的就说清楚了,它在不同的JDK版本当中,底层的操作到底意味着什么,那那大家下来呢,好好的把这个内容呢梳理梳理,那如果呢,你作为一个被面试者,哎,想必呢,哎,你要是都清楚以后呢,把这个事儿呢,给对方解释的时候呢,一定是可以说透彻的,那如果说你要是一个呃面试官的话呢,那我觉得的话,你如果想是去为难这个被面试者的话呢,一定程度上,那我觉得你也能够达到你的一个目的是吧,这个通过一个看似相对比较简单的问题,因为呢,咱们在开发中对于string呢,还是比较常用的,那越是常用的问题呢,可能有的时候我们就越容易忽略到。
01:00
它底层的一些实现啊,反而呢,这个还是做一道比较难的面试题会出现对吧。啊,其实越是生活当中,比如说我们最亲近的人,自己的父母啊等等啊,尤其是父母这个啊,在我们这个工作之前的话呢,其实都是父母给我们投入这个钱,对吧,那真正工作以后呢,你可能随后呢又要谈对象,然后呢,结婚以后呢,要生孩子,其实你的精力呢,你看都就放在这个下一代身上了。啊,有的时候我们就特别容易忽略对父母的一个关心和管理是吧,看似呢,最亲的人,反而有的时候呢,我们关心呢反而会少一些,哎,这个大家也得需要去注意是吧?哎,就是我们惯性思维呢,可能会有一些呃,不自觉的一些做法,但是呢,我有的时候我们还得去理性的想一想,看看是不是做的到位啊,OK,哎,就像我们这道题是一样的,那么回过来的话呢,咱们接着呢谈下一个问题,这个下一个问题呢,是提到了关于这个in inter的一个效率测试。这个效率测试,注意我这呢是从这个空间的角度呢,主要想谈论的问题,主要呢是想从这个空间的角度来谈论这个问题,OK,行,那么这个代码的话呢,直接也是写好了,这个我就直接放在这个位置上,咱们直接来这来看啊行,嗯,这块的话是这样子的一个考虑,我这呢先声明了一个string形了一个数组,这个数组的长度呢,是1000万是吧?诶1000万的这个长度,把它的长度呢定义成是一个全局常量了,然后呢,在我这个main方法当中,我先定了一个in的一个数组,哎,这个数组的长度就是十,放的这个值呢,就从一到十,然后接下来的话呢,我们想给这个词中形的数组1000万是吧,这么长度的数组元素去赋值,一开始的这个值呢,全都是no,那赋值的话呢,我们就做一个for循环,便利一下你这个磁钝形的数组就可以了,那这里边负的这个值呢,就来自于我们这里边的这些数据。
02:41
啊,那这里边因为你这是1000万,我这呢只有十,那怎么办,就我们十个呢,放完以后呢,我们在下一下一轮的时候还放这十个,下一轮还放这十个,言外之意呢,就是我们这个new string,它的这个核心的数据呢,其实就是不断的去重复我们这个一到十,就是这样个逻辑行,那这呢,我是写了两种不同的写法,那一种方式呢,就是我们直接呢去new这个string,哎,通过这样的方式呢,我们去获取的这个inte数组中的这个数据啊,诶循环的就不断的去获取。
03:07
那另外一种方式呢,就是我们在这个逆完这个轮之后啊,后续我们又补了一个叫inter。诶后续呢,补了一个int这样的一个操作,那么这两个的话呢,我们看一下这个不具体的这个执行的时候,它这个区别在哪啊,一方面呢,我们看下这个时间,其实时间这块呢,我们不是咱们重点要关注的,咱重点要关注的就是这个空间上的一个啊效率测试啊。空间使用上OK,那怎么能够体现出来这样一个区别,其实大家呢,如果有过相关的经验的话呢,你应该知道我们在开发当中呢,如果大家适时的去加上我们的呢,实际上呢,是可以节省我们的这个内存空间的,那下边呢,就咱们来证明这个事情好,那咱们现在呢,整个环境呢,都是在这个1.8当中。嗯,这块呢,其实跟我们这个版本啊,就具体没什么关系了啊,但是咱们这块呢,稍微的说明一下,但是在这个1.8的这个环境当中来执行的下面呢,我把这个程序呢,给它抛起来。
04:01
行画下来以后呢,一方面呢,这块会显示我们花费的时间,那另外一方面呢,这个时间显示完以后呢,咱们下边这个进程呢,也没有结束,而是呢,在这进行了一个阻塞啊这个呢是花了七秒多钟对吧,然后阻塞这了,然后的话呢,我们通过这个叫纤维素VM呢,我们打开看一下。嗯,在这儿呢,我们有个叫充上器,充上器呢有关于内存,内存这块呢,你看就显示了我们关于死string啊,它的一个情况,来我们看一下啊,这样我专门呢把它的一个给定出来啊,OK啊这样行,大家看一下这个string的话呢,它的这个字节数,你看这个目前还是比较多的字节数是这么多,那这块呢,大家得除以1024,再除以124,再除以104,你可能能看到它是多少兆是吧,更形象一些啊这样一个情况啊,行,这块我就先暂时不除了,然后大家看一下这个实例啊,这个实例的话呢,你看一下这个具体的这个是不是就1000万次多是吧?诶1000多万次,言外之意呢,就是我们此时内存当中啊,呃,你这儿呢,每一个对象,咱们这个死锥形的数组呢,咱们也没有销毁啊,因为下边我们也没有执行过相关的这个操作,当然你执行这个操作的时候呢,我们就暂时也还销毁不了是吧,就是我们内存中的数据呢,既然没有销毁,所以每一个死string呢都保留着呢,一共是1000万多。
05:16
那因为还有一些这个系统需要的一些这个字符串了,对吧?行这呢是这个情况,然后把它呢停掉,停掉以后呢,我们接下来呢,诶回到这个代码这个位置,我们把这个呢位置做一个调整。哎,把它注入掉,把这个打开,这个打开呢,我们用的是这个in啊,大家想一下这个区别在哪,我们再去执行一下。可以了,对吧,那执行起来以后呢,一方面发现这个时间呢,还都有一个缩短,这呢是一方面,然后的话呢,我们再来看一下这个程序啊,把它那关掉以后,我们再重新的把当前这个进程呢,给它点击一下抽像器,然后点一下这个内存。啊,内存在这儿是吧,我们这个再往前拽一下。哎,这么着。好,大家看一下这个区别呢就来了。嗯,跟这个我们做个对比,哎,这个稍微诶有点偏是吧?行,你看我们这个操作的话呢,这个string,呃,一方面呢,我们看下它这个内存的一个占用,哎内存占用的话呢,在这儿啊,稍微不是特别好看哈,你看这有两个逗号,然后这个前面这个逗号前面是有三位,那这呢也是两个逗号,它的前面只有两位,显然的话呢,我们下边这个操作这个string呢,占用的内存空间是不是要更少一些,这是其一,那其二的话呢,从这个对象的角度来看呢,诶大家发现呢,是不是也会相对水相对来说少一些,你看我们这块呢,是这个5300 5231,前面呢是140啊140万就是呃是这么多,然后你上边这个呢,是在这个前一个逗号之前呢,还有两位啊,1000万多。
06:38
啊,这个呢,就是100万多是吧,那这个差别在哪呢?就是相当于我们下边这个操作啊,其实呢,这是一个双向证明是吧,从字节角度呢,我们能够证明出来,咱们使用in特的话呢,就是更节省内存空间,这是其一,那其次的话呢,就是内存空间的节省,其实也体现在我们这个实力数维护上呢,它也更少一些。没问题对吧,这呢就我们看到这个结论啊,然后大家呢,可以通过我们这个程序叫接VCVM的来看,或者的话呢,大家还可以这样啊,比如我还是先测试上边把这个下边这个注释掉,咱们这呢是不是有个j pro是吧,把它呢打开,咱也可以呢,用这个j profile呢进行测试一下,它呢也是一个商用的啊这样一个软件啊JVSOVM呢是我们JDK自带的一个分析工具,行这呢一个叫life memory啊点开。
07:24
点开以后的话呢,大家就能看到我们当前这个内存当中啊,这个砖的一些情况。哎,大家看这。这呢是我们说的这个磁钝对吧,那当前的话呢,诶很明显的看到我们也确实有1000多万个这个实例,而且呢,这个内存的占用呢,你看关于string这块,它显示的就240兆嘛,哎这儿呢是给我们把单位呢都做了一个换算是吧,果真收费的就是不一样啊行,这呢是我们说的这个场景,我把它呢就诶结束了关掉,哎这呢,你看这时候花的是这个三秒多钟对吧,还三秒多钟,就是右运行的话呢,比我们刚才这个省的时间呢要多一些,然后的话呢,我把上面这个呢给它注入掉,把下面这个再打开。
08:01
那此时的话呢,我们再去使用一下这个j profile,我们把它抛起来。嗯,好了,然后再点一下就叫life memory啊嗯,点开以后的话,这时候大家再看我们这个词string,此时的话呢,它这个维护的这个个数啊,这是它维护的一个个数,你看跟我们这个比的话,这个我们逗号前面是一个三,这个逗号前面是个十,显然呢,维护的个数呢,实例数那就更少了,那其次的话呢,你看上面是240兆,现在呢,咱们只是多少多少KB。多少多少KB,你这块除一下80422这块,咱们还得用一下这个计算器是吧。哎,看一下8042,咱们除一个叫1024,哎等于这呢就是多少兆呗,一共呢是78兆多,那跟我们这个240兆比呢,肯定也有差距,哎这呢是很明显的这样的两个对比,OK,这呢我就把它关掉了。行,那这呢,你看这个花了这个一秒多钟啊,就是通过我们这个程序的对比,咱们的时间上呢,其实不是主要要强调的问题,主要想强调点呢,就是当我们调用这个in证方法的时候呢,给这个数组元素赋值,结果呢,我们发现呢,从空间角度上来讲,那使用上特以后呢,我们尤其是当你程序当中有大量。
09:16
重复的这个字符串的时候呢,我们说使用上这个in是可以大大的节省内存空间的。啊,这呢我们是一个结论啊,把这个呢稍微的写写一下,就大家呢,不是说咱们现在讲这个程序呢,说一个热闹就完事了,大家在开发中呢,你要适当的去使用上这个in,那结论上呢,就是呃,这个对于字符串啊,如果或者这个对于程序中啊。哎,对于程序中这个大量存在的字符串啊,这个尤其啊其中存在。哎,存在这个很多,哎,重复字符串时。那我们说呢,诶使用这个方法,哎,它使用方法呢,诶可以是不是叫节省内存空间啊。
10:09
对吧?诶大家呢,看是不是能明白这个道理,你想一想,就是我们如果是这样的方式,你去new的这个对象,这个new呢,咱们前面也提到过了,一方面呢,是会在我们这个对空间当中,你这块呢,是把这个对象真的给拗一下,这是其一,其次的话呢,我们在这个常量池里边是不是也会维护一个这样的一个呃字符串常量的一个实例,对吧?呃,当然你每次去拗的时候呢,当我们来了一遍一到十之后呢,后边呢,这个常量池里边倒不会说每次给你再去放一个重复的一了,呃,常量池里边不会放一个重复的数据,但是的话呢,我们这1000万的这个呃,String的对象是不是都会造出来啊,又由于呢,你放到这个数组中,数组中也没有这个被释放空间,所以呢,我们真的在内存中就维护了1000万个这个string的对象。那这是占用的一个情况,然后呢,如果我们要使用下边这个情况呢,大家想这个情况的话呢,虽然说咱们首先呢,也会去拗这个对象。对吧,也会去用这个对象,然后同时的话呢,它这个常量指标该维护还维护,然后当我们去调离in特方法的时候呢,此时的话呢,咱们返回的是不是,哎,你比如说对于数组来讲,这个数组当然你也是放在这堆里边了啊,哎,这个我就这呢是你这个数组的引用啊,这个比如引用是在这儿的,这个你要在方法里边的话呢,就这样的,咱这其实是个全局的了,是吧?哎,就是数组的具体的元素呢,这块它指向的这时候呢,就不再是你扭的这个对象了,而是我们这个常量池里边你放的这个实例。
11:27
诶放在这个实例,而我们前面new的这个对象呢,由于你不用的话呢,实际上后边呢,也就可以做一些销毁,所以呢,使得咱们下边这种操作呢,它并没有在内存空间当中创建过多的词润,或者换句话说呢,是创建完以后呢,我们后期呢,就做了一个哎就是销毁是吧?哎做一个销毁,我这呢没有打印那个呃垃圾回收的那个信息,那实际上呢,是有过这样的一个呃清除的OK啊这呢是我们要强调一个点,然后通过这个呢测试,咱们想说明一个结论,大家看一下说这个大的网站平台需要呢,内存中存储大量的字符串,比如说呢,像这种社交网站啊,很多呢,都存储了像北京市啊,海淀区啊等等这样的一些信息,那么这个时候如果说字符串呢,都去调用这个T方法的话呢,我们就会明显的降低内存的一个大小。
12:15
哎,想想是不是这么回事啊,哎,因为呢,你重复的数据呢,我们都从长染池里边去用,就用那一个,你就没有必要呢,用堆控验轴你用的那个了,哎就可以节省我们的内存空间,好这呢就是我们这个结论啊,大家呢应该能够听明白。
我来说两句