00:00
我就开始写这个代码了,String s1这呢我写一个ABC,写了一个ABC,然后呢,我在S1,嗯怎么办呢,我改成一个hello,嗯,这个改成hello,这样整,这样整的话呢,这就相当于是一个重新赋值了,是吧?嗯,我这样这样处理一下啊,我string s2这我也叫ABC,这叫ABC,然后呢,我把这个S1呢改成hello了,那此时的话呢,我们来看一下这个S1它的一个值,还有这个S2它的一个值。啊,这个目前呢,我们要说这两个值的话呢,还是比较简单的一些的啊,比如先说这个S1吧,变成什么了,Hello,因为你毕竟重新赋值了是吧,那就是我们要说的是这个S2呢,是ABC还是hello呢?哎,它是ABC,这个呢,好像还很难从这个面上直接说清楚,它所谓的叫不可变形啊,咱们先运行下我,然后我解释啊。
01:06
Hello和ABC,这个应该都清楚,那么为什么还拿这个例子去说明这个叫不可变性呢?是因为有这样一个点,就是咱们通过这样的方式,就是直接呢,我们给这个字符串去赋值,而不是new的。像这种方式呢,哎,我们把这个呢,你可能叫可以叫做叫什么叫字面量啊,叫做字面量。就相较于咱们前边呢,讲一个对象呢,都得去new string呢比较特别,它明明是一个类,但是它的这个对象赋值竟然不用new直接就可以写,只有这个string是这样子的,但是从这个角度来看,很多人潜意识当中总是把这个string误认为是基本据类型,其实也是有点道理的,因为只有我们基本数据类型一个I才直接赋值,正常一个对象呢都得去用啊,所以呢,你会把它总是潜意识当中感觉它好像像基本书类型一样,是因为定义上呢,它比较特别啊,像这种定义方式呢,我们就称作这种字面法字面量的这种哎定义方式啊,那么对于这种自变量的定义方式呢,我们首先要说一个点,像这里边这S1和S2它俩呀,在内存中用的是同一个。
02:24
怎么证明这个事呢?那很简单,就是在这个位置,我就直接呢去比较一下这个S1是否等等于S2,两个对象用等等比较的是什么,对地址值。比较S1哎和我们S2它的一个地值值就是我们实际你存储数据的这个值啊呃,这个这个地值,这就我们叫的地址值了,那么此时的话呢,我们比较一下,你会发现他们二者呢是出诶因为我这块改了是吧,我先这个得注释一下啊。
03:08
哎,这不有个处吗?那说明呢,就是这两个呢,在内存中是不是指向的是同一个呀,哎,这块呢,咱们其实我这个PPT里边画了很多图哈,这个相对来讲给的比较丰富了,咱们呢,稍微呢再画一下这个事儿。CTRLC1下来这样的两行代码,它呢在内存中呢是长这个样子的,这呢是一个占空间,这呢是一个堆空间,只是呢,咱们现在其实用不着这个堆,哎,这呢是一个叫方法区。先表示出来,这个呢叫站。
04:03
嗯,方法区这呢,是从我们这个内存结构上来讲,这三部分呢,我们看到是并列关系,在这个方法区当中。有一部分呢,叫磁串常量池,当然这个呢,我说的方法区当中有一块叫磁符串常量池,呃,这个事呢,其实还得看一下JDK的版本,哎,这个咱们先把字符串呢先说清楚,然后呢给大家再说一下这个JDK它也有不同的变化嘛,六完了有七七万六八八,后边还有九十十一啊这个内存结构呢,在划分上稍微有一些区别啊,然后呢,我们再说这个小的区别是什么啊,暂时的话呢,我先画一个大家通常认为的一个稳定的版本啊,或者都比较认可的一个版本啊,在这个方法区当中,咱们呢,是包含什么呢?叫自符串常量池,哎,它是包含足串常量池的,那不妨呢,我这就呃就把它就认为是常量池了啊,因为咱们现在考虑的就是string了,哎,外边呢,你说它除了常量池之外,还有别的东西啊,集合在一起叫方法区了,那么我们这儿呢,声明的叫ABC。
05:13
实际上这个ABC呢,它不是在这个推空间中生成的,是直接在我们这个站里边。嗯,在这个位置呢,它有一个内容就叫做ABC,然后呢,我们在这个,嗯,站里边呢,这不是声明了一个叫S1嘛,那这个S1的话呢,你声明叫ABC,我们会在常量池当中给你造一个。造一个前提是你这时候没有啊,哎,首次使用没有,那我就给你造一个,哎,然后呢,我指过来,那么此时这个ABC的这个首地值就给了我们这里边的S1了,比如说这个首地值呢,就是0X啊1212吧。行,这是它的这个地址值,就相当于是你这里边儿的这个值。
06:04
哎,0X1212啊,那么这是第一行代码,然后第二行代码呢,我们在站里边呢,又声明了一个S2。哎,这个S2呢,也复制叫ABC,这种复制方式的话呢,我们都认为这个数据呢,是保存在方法区的常量池当中的,哎,那么常量池当中注意是不会存两个相同内容的字符串的。啊,就意味着我们这也是个ABC,我先去池子里边找一下有没有一看有有的话呢,我就要复用了,所以我们会把这个呃,1212的地址呢,给了我们的S2。那给了S2,那么我们这个S2呢,它就也指向了咱们的这个ABC了,那进而的话呢,我们如果去比较等等,显然呢,它俩是相同的,能行吗?哎,这个呢,要注意一下,通过这呢,咱们说了一个问题啊,第五个就是我们叫什么呀?诶通过字面量。
07:09
字面量的这个方式啊,去这个声啊,或者要给呃一个字符串赋值,那么此时的这个呃字符串值,哎,我们说声明在字符串常量池中啊,这个自变量这个方式呢,哎,你可以再注意一下,它呢,就是区别于咱们说的这个new方式啊。哎,具备这种拗的方式呢,叫做自变量的方式,它呢是从呢常量池当中,而我们这个常量池这个多说一句啊,这个字符串。常量池中哎,是不会存储对相同内容的这个字符串的,所谓的相同内容呢,这个你可以理解为咱们拿那个ecos去比较的,Ecos还得是这个重写以后的ES啊,就是真实的我们去看内容了,而不是看地址的啊,就像我们这里边ABC真的你去看内容了啊,内容呢,如果有一样的话呢,呃,这个我就不会去再去新造了,常量池里边呢,只会维护相同内容的一个串啊,相内容的一个串好,那么就是我们现在看到这样的一个情况,那么接下来呢,我这个S1呢,我给它复制为hello了。
08:29
那复制为hello的话呢,那我们就得看一下,这个时候呢,是把我们这个ABC改成了hello吗?不是的,哎,你想想我们这个hello就先这样说吧,咱们现在的ABC,咱们说的底层是不是用这个Y6存的呀,那个Y6长度是几啊,哎,就指定了就是三,那你现在你改成hello hello,这显然是不是五个了。那数组的长度已经确定了,咱们当时讲数组也说过这是三了,你能后边再加两个,不能,是不是得新造一个啊,新造一个,那你想我们这个Y6,我是不是final的final,你能给这个现有的这个Y6重新附一个值嘛,不行对吧,不行啊,就是你你不可能拿着这个还是这个VALUE6,就是还是用这个1212这个所谓的地址对应的这个数组,你再重新的给他指定一个,这不行,因为人家数组是final的啊,那这时候呢,我们只能是再去心,哎哟。
09:33
新造一个,新造一个我放到把这个往上放一点吧。我新造一个这个的内容,我们改成了叫这个哈。这个不让往这S,嗯,不一样了位。
10:01
CTRLXCTRLV。行这样啊,那我们这呢,就重新呢,再去定义了一个叫做hello,那你定义完hello以后,哎,这个时候呢,我们又会有一个新的地址啊,新的地址,然后你把这个地址呢,给了我们此时的这个S1啊,这个SSE的这个地址呢,就不要了。那具体的地址我就呃就不写了啊,那你知道它这个新的地址,然后呢,我们这个S1呢,就指向了这个新的地址了,这个时候呢,并没有对我们S2构成影响,S2呢,人家还是ABC,所以这时候呢,我们体现了个不可变性,什么意思呢?就是你不可以在原有的这个呃位置对我们这个Y6数组重新赋值啊,不可以在这重新去赋值啊,这呢体现的叫不可变性的第一个点啊,体现我们这里边的第一个事情啊,就是当对字符串啊重新赋值时,我们说需要是不是重新指定这个这个内存区域啊。
11:09
哎,重新去指定一个内存区域,然后呢,这个呃赋值啊,然后不能在这个原有位置,或者叫不能使用,呃,原有的什么呀,这个VALUE6啊,进行赋值,因为原有的VALUE6呢,人家是一个final的啊,这是第一个点啊,这个清楚吧,好这个就过了啊,然后接着。那这个我加上一个这个行吧,这是第一个事儿,然后呢,再来说一个问题,再来说问题,我这比如说这个string来一个S3吧,这个S3呢,我还叫一个ABC,然后这个S3我现在给它来一个加,等于一个DEF。诶加等一个叫DF,相当于在我们现有的这个字符串的基础上,我后边给大家又拼接类一个内容啊,那么又拼接了一个内容,那首先那个S3是多少,这个应该没有任何意义,是不是就ABCDEFF啊。
12:14
对,那这块呢,我们要说的是,就是你在现有的基础上后边拼了一个内容,这个能在原有的位置往后加吗?也是不可以的啊,这个也不可以,这个关于这个呢,内存中放哪,咱们一会儿再详细的说啊,首先你明确一下,就是我们在现有的字符串到后面去拼接一个内容,就那这是咱们相当于来了一个S3哈,这个S3的话呢,相当于一开始呢,是不是指向了也是它了啊,这个S3呢,我们给它后边拼接了一个呃,DEF,你还得去新造一个ABC,呃,DEF。哎,还得去新造一个指向这,那咱们证明这个事呢,咱们就看一下这个S2呢,变没变是不是就知道了,咱们因为S3呢也叫ABC,只要你这个S2啊,因为你这块呢,没在这块改哈,是新造的,只要我们S2还是ABC,那说明呢,你这个S3就是新造的,回过来这俩呢,一开始这不是共用一个吗?啊然后这时候呢,咱们去打印一下这个S2。
13:21
是不是S2还是ABC,那说明呢,就是你这个S3呢,是不是新造了一个,哎对的啊,哎在这呢,我们再写一下,哎第二个点就是嗯,当这个对现有的字符串哎进行连接操作时啊,也需要。哎,重新指定这个内存区域复制,诶复制,然后不能在原有的这个Y6上来进行复制,好这个呢,大家也去理解啊呃,这是我们说的这个第二个点,那么还有一个点。
14:08
还有一个点,还有点呢,我现在定义一个呃S4啊,我也叫ABC,然后呢,我这个S4咱们后边呢,会说这个方法叫replace replace呢这个方法这块你就啊出来了是吧,就是你调完以后呢,它其实默认能给你显示一下,你看这块呢,已经错过了没有了,这个咱们说的快捷键CTRLL斜杠啊。啊,这一洞又没了control斜杠这个呢,你。先把这个补上,CTRL斜杠。诶果真不一样啊,哎,又没有了,行,那就你看这个第一个啊,我们可以把一个old的叉是不是改成个新叉,哎,我这呢,比如说我们把这里边的A,我呢给它改成是一个M,把A改成M,好这我就做了一个replace的一个操作,那这个replace操作的话呢,我们al enter一下,诶你得给大家去接收一下,我们这叫S5了啊行,改成S5了,我们去打印一下这个S和S5。
15:14
看一下S和S5变成什么了?你看啊,先打的是S4ABCS5MC,说明S没有变,那这个怎么去体会呢?就是说嗯,其实还是要看的话呢,还是在这里边啊,我们说一下就是我这是不是有个S4啊,S的话呢,咱们一开始也指向的是它,然后呢,我这S呢,把里边这个A呢替换成M,你会发现呢,是不是没有在这改,没有在这改,而是呢,咱们新新造了一个把A改完以后呢,变成M了,叫BC,这个S呢,呃,这个这个改完以后呢,这个叫S5了啊S是不是还是它呀。
16:01
相当于我们对这个内容是不是仍然没有进行修改。啊,这个我看S都是ABC了,我都用不着再去看S2了,S2是不是必然还是ABC,嗯,那也就是说啊,这个注意听哈,这块呢还挺细致的,那也就是说咱们刚才那会说的呢,说哎,我原来叫ABC,我现在改名叫hello了啊你说啊,那是因为你这个数组啊长度变了啊,那你得去新造一个数组啊,这个呢还好理解,但是目前呢,你会发现我这个数组长度都没有变啊,你在现有的这个数组基础上想改一个某个位置上的字符是不是都不行啊,我A我没有说把你这个数组变长了,变长咱们知道数组变不了长,你只能重新指定了啊,那现在的话呢,我们没有变长,我只想把你这哎角标为零的这个元素改一下,这都不可以,那也得去重新去造。哎,这个都不行了,那进而呢,我们进一步证明这个string啊,它就是叫不可变的字符序列,只要你对这个字符串的这个内容进行任何的修改,都必须重新造。
17:10
原有的这个呢,都不能动,哎,这就叫做不可变形啊,把这个点呢,咱们写到这儿啊,这是第算是第第三个了啊,这个呢是咱们叫当调用。调用什么呢?叫string的replace方法时方法啊,叫修改这个呃,指定的啊,或者叫修改这个字符,这个reppla方法它有两个,一个呢是修改一个字符,你也可以呢,连着改啊,比如我想把AB啊改成M啊,这个这个这个MM其实也可以改个字符串啊,就是当你修改这个字符或字符串时。啊,修改指定的吧。
18:01
哎,内部指定的字符或者字符串时啊,我们说也必须重新指定内存区域进行复制,哎,不能在这个原有的这个Y流上呢进行赋值,好,那通过这三点总结一下,我们想描述的就是string代表着不可变的字符序列,大家呢去强化对这个知识的理解,以及呢,我们刚才提到了通过这种字面量的方式呢,咱们是将这个数据呢定义在常量值当中的,好这是我们关于词锥呢第一个问题。
我来说两句