00:01
行了,同学们,那咱就接着再往下了啊,再往下了。呃,那么我们上节课呢,主要是说了一下这个final啊,但是这个final呢,我们到目前为止还没有说完,我们得接着往下看呀啊。但我们也可以简单回顾一下,我们刚才讲了什么啊,刚才有同学就是确实这个问的这个问题我在课堂上讲过了啊,讲过了,课堂上讲过了。这可能就是线上的一个问题,各位啊,其实你不是学不会啊,你不是学不会,我觉得嗯,有可能是。有可能是你控制力,控制力不行。啊,就是确实是不止是这一个同学啊,咱们可能大部分同学都存在这个问题。啊,大部分同学都存在这个问题啊,所以说嗯,咱们也尽快啊,尽快基本上我看差不多。呃,这块应该在3月10号左右吧,啊,差不多到时候再看啊,现在这个时间还先先不定啊,先不定咱们继续。啊。
01:01
对自制力就是自控力比较差。可能在家的话,你这个一会就干别的,一会这个你你有一句话你没有听明白,你没有听见,你你就迷糊了,你就不知道我什么了啊。刚才咱们画了一个图吗?不是。是不是?在哪啊?这个图嘛,是不是哎。它呢,去指向P这个变量,去指向这个对象,那P呢,被final修饰表示P呢,没有办法指向别的对象了啊。但是这个P指向的这个对象里边这个年龄是可以改的。因为你对象没变呀,内存地址又不改,0X1234还是P还是0X1234里边保存的还是0X没变呀,指向那个对象里边的可以可以动,没问题啊行,这是刚才问的这个问题啊。
02:07
行,那么这是我们,呃,上节课所说的,那么接下来咱们这个final还得接着往下看啊,还没完事,一会儿我们来个大的总结啊,我们在这个里面来个大的总结,在这儿写一下啊。来点右键,我们西区新建一个叫final test03啊叫final test03。来啊,呃,大家有没有思考过final,如final修饰的变量,我们刚才一直说的是局部变量,对吧?那么final如果修饰实例变量会是怎样的?嗯。就是修饰实例变量会是怎样?就我们可以研究一下这个问题是不是。Final修饰的实例变量呢?来public class,然后我们叫final test。
03:01
零三。问,方法?来大家看啊,我在这里呢,有一个普通的加油类,这个加油类呢,就叫user吧,User user里边有一个年龄in类型age。这个变量我们称为什么呀,叫做实例变量,是不是,哎实例变量。那么这个实例变量这一块,如果我们加上翻译到修饰的话,会有什么问题?大家思考一下。就总之万变不离其宗那句话你还记得吗?就刚才那个重点。我说叫万变不离其宗。是不是怎么说的。只要是变量怎么着。Final修饰的变量只能怎么着?
04:03
复职几次啊哎。一次。引用了咱们同学们的一个名言啊,名言final修饰的力量只能复制一次,这个到哪都好用。就这句话啊,这句话到哪里都好使。啊,Final修饰的实例变量,各位实例变量是不是变量吧。他肯定也是变量对吧。但是我不知道大家有没有这个。印象啊,我之前说过实例变量,如果程序员不给他手动赋值的话。系统呢,会给它附一个默认值。这个还记得吗?就是,你是否还记得这句话?是否还记得?
05:00
实例变量如果没有手动赋值的话。系统会。默认之。那如果你是散公司的Java软件架构师。如果是啊,当然可能现在不是是吧。你看到程序员在这个变量前面加了一个final。系统。你觉得还。还能不能给它赋一个默认值零?如果系统自作主张。默认给它赋了一个值。这样设计是不是不太好啊?大家思考一下。
06:03
你看伟斌说的很有道理啊,说所有,所以就一直是默认值零。我们来看一下。这个如果我是这个。软件架构师啊。我一看到程序员前面写了个final,我肯定怎么着啊。我肯定让他手动附上值,我可不敢给他复制,万一以后沾染上我咋整?是不是怪我喽,怪我给他赋不认职喽,是吧?因为赋值只能赋一次,还记得吧?是不是赋值只能赋一次?这句话是不是永远是万变不离其宗?Final修饰变量只能赋值一次,如果系统默认给它附上值,给它赋了一个零,我问你是不是以后再也没有机会赋别的值了,像这种行为,我问你系统它会不会给你附上默认值呢?
07:01
如果给你附上默认值,你成全会不会怪我?这个Java会不会怪我呢?所以我的我的我的系统会不会要求说我我用final修饰的话,我会不会要求成全你必须手动附上值,我不管给你负不任职,他系统会不会这样去设计这个东西。就是这个没有为啥各位啊,这这个其实只是一个什么呀,我我只是什么呢?只是其实是一个设计的一个问题,这个当时我在想啊,Java的这个软件开发团队,他们肯定开了一个小会。他们肯定会开会决定这件事情。就final修饰这个实例变量的话。我要不要给他默认值,我要给他附了默认值final修饰的变量只能赋一次值,以后成就再也没有办法给他重新赋值了,那说我要给他附上一个默认值零的话,这样显得好像我多管闲事了一样,对吧,我这系统多管闲事了一样。那三呢,这帮人他会不会开个会说,但凡是final修饰的实例变量,必须得手动附上值,系统不管默认赋值呢?会不会这样去决定这件事情呢?我们来编译一下就知道了,Final test03这个程序啊,这个Java我来编译一下,看这个程序有没有问题。
08:06
C我们一下final。你看,变量age未在默认构造器中初始化,第十五行是错误的。啊。看见了吗?哎,你看。他错误信息是这个,嗯。变量年龄没有在默认构造期中初始化。他说的比较深奥,你不太懂这个我删掉了,删掉了。你可能很难去理解。但是我把final去掉之后,这个程序就能编译通过。你看。你看。是吧,你把final加上就不行。这可见呀,散公司他怎么着啊?它有一个在这里有一个语法,什么语法就是实例变量,如果用final修饰的话。
09:04
要求我们程序员必须手动给他复制。不能采用系统默认值,你发现没有?这就不行不行不行不行。那不行,他就要要求你必须手动附上,你必须手动,你不能采用系统默认值,我可不管你这个,就这就这意思。啊,所以这里呢,有一个结论是什么呢。Final修饰的实例变量。系统不管。负默认值。要求程序员必须手动复制。大家觉得这样他这样设计合理不合理,你们觉得他这样设计合理吗?我觉得倒是挺合理的啊。大家想一想,这个合理吗?这个设计的。
10:03
Final修饰的实例变量。这种东西系统它不管负默认值,它不管你负这个默认值。要求程序必须手动复制,他不管。合理吧。哎,我觉得这件事儿他其实甩锅甩的挺好。他甩锅了呀,你没发现他甩锅了吗?他不背锅,你看程序不背锅。理解吧。Java程序设计。不背锅呀。甩锅甩的很好啊。叫甩锅甩的很好啊,就是你final修饰的实力变量,这种我可不敢给你负默认值,我给你负上不认值你又埋怨我了,这样吧,Final修饰的实力变量你自己赋值吧,我不管了啊,他就这意思,你看。你看形象不形象是不是,哎,Final修饰的这个,因为变量这个东西只能赋一次值,这个语法是固定的,谁也谁也改变不了的事儿,对不对,你既然定了这个语法,你的语言自始至终,不管你是什么变量,我都得是只能一次值。
11:13
它是以这个语法作为前提,然后紧接着怎么着,他又说了,说实例变量东西,你要是说你不加final,那好,那我可以给你赋一个默认值,以后你可以再怎么着啊,诶再给他重新给他改值,无所谓,但一旦被final修饰之后,大家都知道这个变量啊,这个东西啊,怎么着啊,他就嗯就就就就就怎么着就就就不能再重新复制,只能复一次值。那这个时候呢,我们这个散公司的这帮人,他就他就想了个办法,说既然是这样的,那妥了,那final修饰的实例变量你们自己付吧,我可不敢给你们付系统默认值,我要给你付一个系统默认值零,你到时候可能会埋怨埋怨我对吧,埋怨我这个那个这个那的是不是,所以说我不背这个锅啊,锅甩的很好,甩出去了。所以不管大家怎么去理解吧,总之这里呢,你只要记住一句话叫什么呀。
12:01
哎。叫做实例变量final修饰的话。我们这个变量必须得手动复制。不能采用系统默认值是不允许的,你看。对吧,哎,你别过不去啊。你看是不是,所以这个不行啊,那我们再来一个。嗯,比如说我们再来一个实例变量,各位啊,这样写行不行,Double身高。呃,身高等于一米八。这样编译行,你看当final修饰的呀。修饰的变量。对吧,你看。这次可以了,你看。是吧,哎,这次可以了。看见没?
13:00
就你这样做不行。编译器报错啊,这个呢可以。可以啊,因为怎么着,因为程序员手动什么赋值的。因为程序员手动赋值。这就可以。来,我们再来一个实例变量。我在这里我再问大家一个问题啊。我再问大家问题,实例变量是在什么时候赋的值?我不知道多少个同学还记得啊,就是实例变量。在什么时候复制?什么时候初始化?构造方法执行的过程中复制。六的时候复制。
14:02
是不是构造方法执行过程中负才赋值啊?就变量是在什么时候赋值,是不是在构造方法执行过程中再赋值啊。对吧,哎。哎,说的很好啊。很好,那么接下来呢,大家注意听啊。那如果说我现在再来一个变量叫final。然后呢,我写一个什么呢,写一个这个叫做double吧,Weight啊weight体重我没有给默认值。呃,我没有在这里给他手动赋值,各位啊,没有赋值编译器肯定报错对吧。是不是,哎,那现在这个等号这个东西,我非得写到这个地方吗。我在构造方法里边直接写上行不行。
15:04
this.wait。等于。80。如果这行代码和这行代码联合起来行吗?就单独写他不行是不是。写上这个变量负上值加个final行不行可以。那如果说我把这个剪切掉,这样肯定是不行,不用测了。但如果说我把构造方法加上去,在构造方法就不给它赋值呢?行不行啊。可以。大家可以啊,可以。为什么这个可以大家思考一下,为什么这个可以呀。
16:09
一次。有道理。赋值一次是有道理的啊。在new对象的时候赋值,这就是我刚才所说的。就是你现在这个变量负默认值零附上去,它实际上也是在什么时候附上啊,这个等号在什么时候执行啊,是不是在构造方法执行过程中在执行啊好,那如果说我在构造方法里边,我给它附上一个值。是在他默认值。只要你给它赋值就行。是这样吗?
17:06
我感觉同学们这块有没太理解。就是付默认值是在什么时候付的,各位。假如说能赋默认值的话,它是在什么时候是构造方法执行的时候赋值对不对,就是说我不知道大家也知不知道这个代码,就是说我现在什么也不写,为啥这报错。给大家好好思考一下,这个这个为什么报错。你编一下,你看报错了,你看不行啊,为什么这报错?原因是大家还记不记得,如果一个类不写任何构造方法的话,它是不是有一个默认的。无参构造有没有听说过我说之前说这句话,并且无参构造大括号里边如果什么也没有的话,它默认会在这里有一个什么?
18:01
有一个wait等于什么零,它默认会有这么一个代码会默认执行,这是系统负默认值是吧?这是不是系统赋默认值是在这个时候,如果我在这个时候,赶在它负这个零之前,我手动的给它附上去一个80的话,大家想是不是也能说得通?对吧。好想一想啊,这块呢,能想明白就想,想不明白的话就记结论啊,能想明白就想,想不明白的时候就记结论。这样就可以。为什么这样可以?我再强调一下各位啊,是因为我这个代码并没有在负80之前付默认值。
19:03
只能在第一行不是啊。不是啊,跟第一行第二行没关系。只要我。敢在什么?系统服。系统赋默认值,注意啊,只要我敢在系统赋默认值默认值之前赋值就行,你听我这句话说的有没有道理啊,只要我敢在什么我敢在啊呃,系统赋默认值之前赋值就行。雨桐老师,第31行系统不会给他赋默认值吗?系统不会给他付一个零吗?为什么你在这又重新给他付了一次啊。注意。系统负默认值零这个等号,它执行的时间是在什么时候执行?是不是也是在构造方法执行的时候,这个零才会负,对吗?
20:04
那如果说我在构造方法里边给他附上一个80,是不是代表他还是赋值了几次啊。还是赋值了一次,对不对。大家好好想想。是不是还是复制了一次?那个零是不是还是没复制上。那为什么这个去掉就不行,那是因为你有一个无参构造,无参过道里边有默认值零嘛,所以它是不允许的嘛。但如果你把构造方法加上去,你这里边给他写上一个,这个其实也是负什么负几次值啊。负一次值就这样联合起来,就是以下这一代码全部组合起来啊,以下这一堆代码全部联合起来。Wait变量也是赋值了几次。
21:01
一次。云老师,他这不是有个默认值零吗?这个我在听调,这个默认值零是在什么时候附上去的,是在构造方法执行的时候才附上去的,而你在构造方法里边手动给它附上值,那么这个时候他在构造方法里面就不会给它负零了。听懂了吗?就是这个意思,就以下这一堆代码全部联合起来,为的其实也还是赋值了一次,但如果说你这个代码删掉,那就不行了。你这个代码删掉它的构造方法以后,无参的构造,无参构造里边会给这个属性赋值默认之零,所以这个时候它不允许,你看它不允许,如果说你把这个给他放开,你给他附上去80,它就不再付系统默认值零了。就就算你这有个默认值,你说老师这个默认值零附上去了没有,各位啊,这个零在赋值什么时候,我刚才问了问了大家半天,我说构造这个实例变量在什么时候赋值。就是说构造方法执行过程中赋值。构造方法执行过程中负值。听懂了吗?就算你有一个变量int I,你没给它赋值,系统给他负这个零往上赋的时候,也是在构造方法执行的时候才给他负的,明白吗?
22:13
你现在这个代码和这个代码联合起来,也是只复制几次,复制了一次。你这么干不行啊,你这么干不行,你这么干你在这给他附上值,和你在构造方法里边写个等号给它赋值是一个意思。是一次还是一次啊,那个零压根就没附上。Final修饰的变量。必须手动复制。但只要赶在什么呀。赶在系统赋默认值之前赋值就行。啊,这个我往深里讲了啊,赶在系统赋默认值之前赋值就行。对,赶在系统默认值之前负的值。
23:03
是允许的,你看一下。可以吧?哎,这样可以没问题啊,但你能不能这么干,this.wait再给它这里,再重新给他付行不行?这个可以吗?行不行啊,来走一个。38不行。看见了吗?这个不行啊,不行。这个可以。但刚才说这个代码必须出现在第一行,这个不对啊,我就不出现在第一行,我system.out点打印输出hello word,我问大家行不行。清明啊,来我们看一下啊。没问题啊。
24:02
对吧,没问题,他不一定是第一行啊,他不一定说,不一定说你这个代码必须得出现在你这个方法的第一行,不一定。你吗?可以,我觉得大家大,我讲的是大家不用掌握这么多啊,不用掌握这么多,你只要掌握一点就行,哪一点。就这。Final修饰的实例变量系统,不管不管。啊,或者系统不负责。负默认值要求成权必须手动赋值。这个手动赋值。在变量后面赋值可以,在构造方法中赋值也可以。终极结论,各位啊,我不管你听明白还是没有听明白,这个终极结论就是这样的反终极啊。
25:02
结论是这样。Final修饰的实例变量系统,它不负责负默认值,要求程序员必须手动赋值,明白吗?必须手动给它附上,而你这个手动赋值,你可以在这个位置上付,可以在变量的后面直接付,也可以在构造方法里边赋,你选择一个都行,你愿意采用这种就采用这种,你愿意采用这种你就采用这种,无所谓都可以,但对不起,您单独写这么一个东西还真是不好使,你写这么一个东西,诶,不好使,各位啊,你写这个东西连上数值好使,诶,你写上这个东西连上构造方法好使,听懂了吗?就是同学们,咱们不要去讨论这个问题了啊,你们这块可能啊,就就还是没有领领会我想要说什么啊,那么这块能够理解的同学,你就去理解,你理解不了的同学,各位我再强调一下啊,终极结论我已经给你放出来了,就在这儿,你永远记住一点就行,Final修饰的实例变量这种东西。
26:04
成这个系统,它是不负责你负这个默认值的,你负值要么怎么着,在你变量后面写上,要么在构造方法里面写上,你选一个吧,你选一个同学啊,一句话啊,你选一个。就行,别纠结啊,别纠结你选一个各位啊,你选一个就完事了啊。对。如果写一个有参构造方法,为什么不赋值也能编译通过?啊来。注释掉。现在这个能不能过去。不行吧?写个有餐的。
27:06
来。还是不行啊。不过去啊。跟你方法有餐无餐没关系啊。你无餐也行,有餐也行,你总之你没给我赋值不行,你没给我附上值肯定不行。听懂了吗?this.s等于S。你S在哪有啊,你告诉我。在哪有啊S。S在在哪有哪有S啊。你z.Sz.SS在哪呢?这里面有S吗?S没有啊,哪有S啊?
28:06
This wait,哦,Wait是double,那当然行,那当然行啦,那还不行吗?我讲的不就是行吗?我讲的就是行啊,我上面不就这么讲的吗,同学。哎呀,我的天呐,那你认识点wait呗,认识点wait。是吧,等于D,那这也算赋值啊,也算这是这也是赋值了,没有采用系统默认值嘛,对不对,这不也算是赋值了,也没有采用系统默认值啊,就是附上值的呀,就行啊。你将来不是有个变量给它赋值吗?我问你,你是不是将来会调构造方,调构造方你你会传一个什么,你是不是会传一个小数过来。有小数是不就行。
29:00
不怎么还没有理解,你跟后面的这个数据没关系,听懂了吗?就你这个数据是一个实际存在的数据也好,你是个变量也好,你就算是变量,那我你程序运行的时候,你调这个方法是不是会给会传过来一个小数小数啊,你小数是不是给他会会给他传过去啊。那当然可以啊,负0.0是可以的,你往上给他个0.0,那是你自愿的,那跟那跟人家系统就没关系了,你0.0就是个数据啊。程序员在有意识的情况下写了一个0.0,那这是你自愿的呀,对吧,你就是想让给他付一个0.0,那无所谓。因为这是有意识的,这是你自己付的,我可不管。这个不是先执行无参构造吗?我不去执行物舱构造也行啊。我不执行无参构造也行啊,我创建对象必须调用无参数构造方法吗?
30:04
不一定啊,就创建这个对象,不一定非得调无参构造啊,调这个构造方法也行啊。没问题啊。嗯,可以啊。明白了。我再强调一下各位啊,这个地方final讲的是什么?我说了还是那句话,如果您没听懂。画复杂为简单,怎么画?这样啊,你就记住这句话就行,Final修饰的这个实例变量,总之你得手动给它附上一个值。明白吧,要么你在变量后边赋值,要么你在构造方法里面给它赋值,这样赋也行,这样赋值也可以,都可以。
31:06
但是你必须得有,必须得有啊,必须得有,就是你通过这个赋值也行,你通过这种方式赋值也可以都行。你得选一个,总之你得附上值,总之我们系统就不负责负默认值了,就系统不负责负默认值了。啊,系统不负责,负默认值。要求程序员必须手动附上。啊。保证在它构造时就要给它赋值,就这意思。啊行,这就说到这儿。
我来说两句