00:01
行吧,那咱们再接着往下看吧,啊,那final这块呢,咱们再尝试着这个扩展扩展行不行啊,咱们再扩展扩展啊来这个呢,我就先给他。呃,清下屏啊。这个呢,我这是源代码先关了,不用看了。呃,这个呢,源代码关了它就不用看了啊,行,这个代码咱们接着往下看,在这里,在这个目录下啊,我还是去新建一个文件叫做final test02.java啊。嗯。Public class final test02 public sta,注意听啊。来。Final修饰的变量。
01:01
如果这个变量是一个引用会怎样?同学们思考一下啊,就翻到咱们之前在上一个例子的时候,我是不是已经给大家说过了,哎,有一个非常精辟的一句话叫什么呀,Final修饰的变量只能。负。一次纸。对吧?哎,这是一个重点final修饰的变量,只能赋一次值,我问大家引用是不是一个变量。引用是不是一个变量呢?答案当然是,是咯。对吧,哎是那么我们来分析一下啊,比如说在这里我有一个什么呀啊叫做user吧,或者说我有个person啊,一个人这样的一个一个类啊。
02:12
那就是保存的内存地址不能变,你看马上就有同学回应出来了啊,在这里呢,我们有一个什么呀?呃,有一个这个叫做嗯age吧,行吧,有一个构造方法是无参的,完了之后再来个构造方法,是有参的,我都给它写出来啊。来这边写上this age age好了,那么这个呢,是无参构造,你看是不是这是有参数的构造方法是不是?哎,这是一个什么呀属性,那么接下来呢,我在这儿怎么着呢?我说person PE new。Person。年龄是20,这个20啊,就进去之后呢,他呢就付给了他。所以这个人年龄是20啊,然后接下来system.out打印输出P一点没毛病啊。
03:07
P去访问这个实例变量嘛,就p1.h呗,是不是好,那么接下来我们来看一看啊,Java c呢,去编一下final times的02点加Y。Java去运行final test02,你看当前程序没有任何毛病,没毛病,老铁们啊,这个程序呢很正常,编一个运行都很正常,那么接下来呢,我在这里画一条线了,各位啊,往下看了,跟上面程序没关系了啊,没关系了,往下看了啊是这样。Person啊。P new,一个person,我给这个人啊,30岁初始化年龄。啊,这等于是创建了一个对象啊,我在这个PE前面加了个final。那你说我这个屁。能不能等于?
04:02
New person。30吧啊,随便随便就就写个30行不行。就你记住一点啊,这个语法永远不变。Final修饰的变量只能赋一次值。这句话是永远不变的。这句话是铁定的道理啊。万变不离。其中。明白,就你再怎么变P也是个变量,对吗?哎,就是你记住啊,代码不管怎么变化。P。也是一个变量。
05:00
对吧?哎,P也是个变量,只不过在这里它有个特殊的名字叫引用,对吧,只不过这里它有一个特殊的名字叫引用。但你说到底它是不是还是个变量啊。你比如说我final修饰的I等于十,那我I呢,重新一个20,这就是不允许的。这就是不允许的。对吧,哎,这个代码我就注释了。注释掉了,各位啊,那你想一想,我们现在这个代码final person p等于new一个person,这是不是一个对象内存地址0X1111对吧。是不是好,那我问你这个P以后是不是只能等号里边是一个0X11,不能是别的,别的东西就不能再变了,对吧?那我问你在这里是不是又重新了一新,只要后这30没关系啊,只你我大家不是一定产生新新象是不是新的内存地址,新的内存地址是不是0X2356啊,0X2356大家想一想往那个等号这附的时候能附上去吗?因为P已经被final修饰了,P里边只能保存0X1111,你让P去保存一个什么呀?0X2356那是保存不了的,对吧?同样一个道理吧,对吧。
06:22
是不是跟30有关系,没关系啊,不管你这个年龄是多大,是不是拗一次,只要拗一次,堆里边会产生新对象。只要扭一次是会产生新的对象,新的对象是会有新的内存地址,新的内存地址再往P上附的时候,是不是附不上,因为P被翻译修饰啊。我们不说了,变量怎么着只能付一次值啊。只能赋一次值啊。明白什么意思吧,所以这个程序啊,就编译就报错了,我们来看。Java c编译final test02.java。啊。你看错误第14行。第14行啊,第14行,你看这个错误跟前面一样一样的啊,无法为最终变量P分配值。
07:06
我们可以打开刚才写的那个第一个程序。第一个程序final test1这一块,这个错误信息是不是跟那个错误信息是一模一样,你看无法为最终变量K分配值。你看final int k等于100,把K呢,附上300说无法为最终变量K分分配值。到了我这个例子说,无法为最终变量P分配值。对吧,啊,这不行。不行啊,所以实际上这个内容我跟大家说一下。没讲新东西。没讲新东西,各位啊,你承认不承认同学们?这个内容是不是还是讲着前面的这个问题啊。前面是不是已经讲过了这个。讲没讲过。Final修饰的变量只能赋一次值。理解我在说什么吗?同学们,理解的话打个一来。
08:00
就这个例子并没有讲新,新的知识点你懂不懂?这个例子没讲新的知识点吧?啊。这个例子在这讲的啥呀?各位。讲的是不是还是之前的那个那个语法。只不过这个变量啊,跟前边有点特殊,前面那个变量是int类型,只不过这个变量是一个引用数据类型。不管你是引用数据零还是我们基本数据类型,只要你是变量,那等号后边负的这个值对吧?哎,一旦被翻到修饰,那我们就不能再变化了,只能赋一次值。只能复一次值。各位啊,行了,那这块的话我们呃。总结一句什么话出来呢?Final修饰的引用。Final修饰的引用是怎么回事?该用。只能怎么了?只想。
09:02
一个啊。对象。并且,他只能永远。只想。该对象想想啊,该引用只能指向一个对象。并且它只能永远指向该对象。赋初始值也算是被赋值过一次了吧。对呀,但现在还局部变量没有初始值。局部变量没有初始值,各位啊。局部变量没有初始值。不像成员变量因。是不是如果说你不给这个F值。哎呀,我的天啥。I对吧,这有初始值啊,局部变量是没有初始值的。只能手动复制。
10:00
严彪,别把老别别把大家啊,带带这个带偏了,别把大家带偏了啊。负初值也算是被复制过,你这个局部变量是没有初始值的啊,只有成员变量才有初始值,现在你看没有成员变量啊。我们都是在问方法里面写的局部变量。是不是局部变量是没有初始值的?啊,跟这个age没关系啊,你不用管age age是这个对象里边的东西。我们现在说的是P嘛。那说的是P啊,说的是P,嗯。该引用只能指向一个对象,并且它只能永远指向该对象,无法再去指向别的对象吧,无法再指向什么。其他对象。来,我们可以把这个内存图画一下啊。
11:01
简单画一下这个呢,假如说是我们的一个Java虚拟机JVM。好久没画图了啊,咱画个图,那么这块呢,咱们有一个叫所谓的方法区啊,我就不说了,在这里呢,所谓的有一个堆内存,在这儿呢,所谓有个占内存是不是好,我们这块呢,我们把这个呢给它。删掉啊好,那么这一块呢,我们写上这个叫方法区,方法区啊,然后这个呢叫做堆啊,这个呢,我们叫做站。好了,那么方法区这块呢,我就不再画了啊,是它的代码片段啊,代码片段以及静态变量啊叫代码片段。代码段静态变量是都在这里啊。不画了啊,那么程序先去执行我们的一个闷方法喽。对吧,那执行闷方法,那行吧,那咱们接下来,呃,在这里呢,我们画一个笨方法,这就是那个焖方法,假如说啊。
12:04
来,这就是闷方法战争啊。叫做main方法战争大致的这样画一下,那么程序先去执行第一行new,一个PERSON20。对吧。皮。呃,我这段代码不画了吧。第12行和13行我就不画了,各位我直接画第17行。和第19行。行吧,17行啊,New一个PERSON30。那就意味着说我们在这里啊,应该是有一个什么,有一个对象的是不是。哎,这个对象是个person对象对吧。哎,Person对象各位啊,Person对象,那么这个person对象它里边有一个年龄啊。是不是啊,有个年龄啊,比如说有个。呃,应该有块空间的啊,一块空间。
13:01
这个空间里面存在多少呢?存的是30。这个30是付给了谁呀?他他付给了谁呀,他他是谁呀,他所以这个对象里边这个H是30是不是。哎,拿过来。嗯。并且呢,这个变量啊,它是一个int类型变量啊,Int类型H。啊,然后接下来这个对象,整个这个对象哪个对象呢。这个对象啊。来就这个对象,这是一个整体的对象啊,这个对象呢,它的内存地址。赋给了变量。明白吗?哎,在内存图上是怎样的呢?在这啊,它有一个什么呀,有个final person啊P。Final呢,它这个变量里边啊,它保存了一个什么呀,对象内存地址。
14:01
这个对象内存地址呢是什么呀?是0X什么呢?1234。明白吗?这个内存地址,这这就这就是这就是那个那个那个那个变量里边保存,这就是那个变量,看见了吗。这个蓝色的框啊,这里边儿,这就是那个变量里边保存的东西。它呢,去指向谁呢,指向这个。啊。指向他。明白吧,哎,指向指向这个对象。那么接下来呢,是什么呢?接下来这个程序啊。他是又了一个新的person。每扭一次呢,它会产生一个新的对象,所以这个时候呢,它会怎么着啊,会在这里啊,再创建一个全新的对象,你懂吗。就在堆里边,又多了一个新的对象。这个新的对象啊,它也有新的内存地址。明白吧,啊,那么这个对象呢,它的内存地址是什么呢?哎,比如说。
15:08
它是什么呢?哎,就是0X2589。啊,假如说这个对象啊,是两个25890X2589,说这块啊得改一下。说你要把0X1234。因为等号吗?是不是负值啊。扭出来之后是不是赋值啊,赋给P吧。那你P里边保存原先是0X1234指向这个对象对吧。那这个时候呢?它能不能变成什么呢?0X2589。能不能不能。不能啊。来,往下挪一挪。就所想表达的意思啊,大概说一下。
16:04
练一下啊练一下。那么你这个数据啊。想从他变到他。而他又指向这个对象。对吧。对不起。这个不行。因为他是不可变的。明白吗?这不行啊,打个叉。对吧,它从0X1234变成0X258九变不了。变不了,最终呢,就没有办法指向这个对象。明白吧,那么也就是说这个P呀,他倒霉了,他以后啊,只能指向这一个对象。
17:03
并且从P出生到P死亡整个过程,它永远指向这一个对象。明白吗?理解这意思吧。Final修饰的这个变量里边保存的这个值不能变。不能从0X1234变成零,X258九变不了。而且它只能指向那个对象。有同学说,老师。我给他付一个囊行吗?可以给P一个吗?我们算不算负值?那是不是也是只是个空值对吧,是不是也算重新赋值啊,能不能负啊。行不行,我们编一下啊。无法为最终变量P分配值。看见了吗?废了。明白吧,粘上就放不了手了。可以给P一个now吗?错误,无法为最终变量P分配值。
18:04
也就是说你P变量里面只能保存0X1234。你连这根线断都断不了了,就相当于你手里拿着一个呃嗯,拽拽着这个风筝线,风筝线呢,放风筝是不是这个风筝线永远断不了。永远断不了,明白吧,你想断也断不了了。可牢了,从你一出生,八粘上这个0X1234指向这个对象之后,这这根线从来就不会断。就不会断啊,不能离婚,不是不能离婚,也不能这样去理解,就是说。这个对象在整个程序执行过程当中不会被垃圾回收器回收。只有你这个方法执行结束。才会被垃圾回收器回收掉。大家有没有意识到这个问题?因为我们曾经说过,如果有一个引用去指向这个对象的话,这个对象它就不能被垃圾回收器回收,整个这个对象它被垃圾回垃圾回收器回收。
19:04
它是这根线断了之后是不是才能被回收。对吧,这根线断不了。所以被final修饰的变量啊,如果是个引用指向该对象对吧,那么这个对象在整个方法问方法执行过程当中啊,它是不会被垃圾回收器回收的。啊,不会被垃圾回收器回收的。啊,当然只有你要是这个方法结束了,因为它毕竟是个局部变量嘛,它毕竟现在在这儿是个局部变量,各位。对吧,局部变量你懂什么意思吗。啊。局部变量就是你这个方法执行结束,这个局部变量内存空间就释放掉了,那他他肯定会被回收对吧,在当前方法执行过程当中啊,这个对象不会被垃垃圾回收器回收啊,Final修饰的引用,该引用只能指向一个对象,并且它只能永远指向该对象,无法再指向其他对象。
20:03
并且,并且在在该方法执行过程中。啊,呃,该。引用指向该对象之后。啊,该对象不会被垃圾。回收机。回收。并且在该方法执行过程中,该引用指向该对象,该引用指向对象之后,该对象不会被垃圾回收器回收,直到当前方法结束。啊,才会释放。空间啊,Final修饰的引用各位啊,这个地方呢,其实呃,也没有什么新东西啊,就是基于我们第一个例子。
21:01
干什么呀,我们在这里衍生出如果变量它是一个引用类型的话。它的特点是拗了一次,你再扭一个新的,你想往上附,附不上去了,因为final修饰的东西不能变呀。那这样的话,在内存图上也是这样,你从这就无法变到这儿了,没有办法指向这个对象,只能指向这个对象,并且这根线你还永远断不了,这根线你断不了。断不了这线。所以这个对象呢,飘不走啊,他也不会被拦截回收器回收,因为有引用指向它。啊好,我再问大家一个问题啊,我这里啊,突然我想到一个问题,我问大家说P呀,现在指向了这个对象,它不能再去指向别的对象了,对吧。这对象不能变了,对吧?好,我问大家问题,就对象里边这个30能不能改成40。就大家一起思考一下啊,就是说呃,引用指向的对象不能变,对吧,引用指向的对象不能换。
22:05
是不是,这对象内部的数据能不能改。大家好好想想,就说我是指向0X1234 0x1234指向你没问题,对吧,我0X1234呢,不能再去指向别的对象,但是我问大家这里边的30能不能改成40,就是这个对象还是这个对象,就我只是把这个里边的30改成40,能不能啊。没问题,没问题。那么我们来尝试改一改啊,还是这个P各位啊,我们干啥?P点。等于40。system.out点打印输出p.is。我们来编译一下这个程序,各位大家看,编译没有任何问题,加完一行final test,零二走。哎,40吧,是不是没问题啊,所以说final修饰的这个对象。Final一旦修饰引用之后,这个引用指向了这个对象,对吧,不能再指向别的对象,但是。
23:03
该引用所指向的对象内部的数据是可以被修改的。啊,所以这里呢,还要注意一点,就是引用只能指向一个对象,并且呢,永远只能该指向该对象,无法再指向其他对象。虽然引用的引用啊,Final的引用指向某个对象后。某个对象。这样吧,虽然final的引用指向对象A后,不能指向,不能再。重新指向对象B。啊,但是对象A内部的数据可以被。修改。你看我这么说大家理解不啊?就虽然final修饰的引用指向对象A后,不能再重新指向对象B,但是对象A内部的数据可以被修改。
24:04
就这个通过这个图你也可以看到啊,我指向你,我就指向你呗,对吧,我不能指向别的对象啊,那很正常啊,但是我所指向的这个对象,这个里边想把年龄改成三十三十改成44,这是没问题的,你这个对象就没动啊,你还是个对象啊。这个对象内存地址还是0X1234啊,我P没变呀,P里边是不是还是000X1234啊,还是指向这个对象是吧,只不过这对象里边这个这个数据是可以改的啊,可以改的来这个呢,我保存一下啊啊这叫。哪个呀,这是对应的哪个例子啊,Final修饰的,Final修饰的引用啊,Final修饰的引用啊,它的情况是这样一个情况啊。好了。这个咱们就说到这儿啊,通过一个内存图,其实我觉得大家还是很好理解的啊,还是很好理解的。
我来说两句