00:00
来同学们,咱接下来继续往下看了啊,再往下呢,我们一起来学习一下空指针异常啊,就是程序在执行到什么情况的时候会出现空指针异常好吧。嗯,我在这个CHAPTER09下。ID plus怎么设置打开多窗口?嗯。这个你得找找啊,你得找一下,这个我也不太清楚,反正之前是可以的,你看我这个是分开窗口的是吧。分开窗口的啊你其实我倒是愿意在这儿多显示。多显示几个啊。在一个窗口里面显示,我喜欢这样啊,我跟大家可能习惯不太一样。I plus怎么设置,打开多窗口,嗯,应该是可以设置的,我记得咱们同学们之前有一个有一个同学问这个事儿来着。啊,不知道从那个。不知道从百度里面搜到没有啊。
01:01
应该是的。大。工程工具。你自己百度吧,百度一下啊,我这是有的,咱们之前确实也有同学问这个事儿的窗口。哦,拆分。排列。横向。平铺。应该是这块啊,你从这儿试试。什么拆分?拆分窗口。其他。拉伸。是不是,哎,你从这儿看一下好吧,从这从这找找窗口列表。找一下啊,应该是在这在这。啊,什么横向平铺啊,什么排列图,看一下这个啊行,那咱们这个先不说了啊,这只是个工具而已啊,只是个工具,那么接下来咱们接着再往下吧,那再往下的话,我觉得要干什么呢。来这个课堂笔记还是给大家记一下啊,画内存图注意事项以及为什么要画内存图解就就不说了啊,下一周看一下这个笔记啊。
02:02
那么程序呃,在运行在什么情况下会出现空指针异常呢?我们把这个研究一下啊来这块呢,我们去写一个程序,各位啊,写一个程序。嗯。Nine point。Test。好了,那么这块呢,咱们这样啊。Public class,我们叫non po test public static void。来这块呢,ARGS。那这个呢,最主要是给大家说一下空指针异常的事儿啊,啊空指针异常这个英语单词呢,它比较长啊,叫non pointer exception啊none pointer exception,那接下来在这呢,有个class啊,这class呢,假如说叫customer客户客户啊客户呢,嗯,他有什么呢?有这个ID。
03:15
客户的ID好,那么接下来我在这里创建客户对象啊,创建客户对象怎么创建customer。Customer customer是不是,哎,C等于new一个什么呀,一个customer。那当我们溜了一个customer之后呢,接下来我们来访问什么呀?哎,访问这个客户的ID,那我们要访问这个客户的ID其实很容易了是吧,这个客户的ID它是个什么变量,是一个实例变量啊。是不是哎,实例变量,成员变量中的实例变量啊,叫做成员成员变量中的实例变量,那么应该先创建对象,然后通过什么哎叫什么呀,叫引用点的方式访问是不是好,那么访问这个客户的ID呢?这块应该是c.ID吧。
04:11
是不是啊,system.out.out.print line打印输出C点什么呀?ID,那么之后大家知道这个ID的值是多少,是零对不对?哎,这个输出结果是零。啊,输入结果是零,来我们来编译一下这个程序,没什么可说的啊,Java c编译一下那pointer,然后Java去运行,Java命令去运行啊,Java叫none pointer test。好,来看结果是零是吧,那现在我能不能给他重新赋值啊,重新给ID赋值行不行啊。那可以啊c.ID是不是C就是这个客户对象呗,就是这个对象呗,是吧,C是个引用,引用点ID等于什么呀,等于比如说嗯。嗯,7521。
05:02
或者9521是吧,哎9521终身代号是不是,哎叫终身代号啊。c.ID然后呢,附上值之后呢,啊,客户的ID叫客户的ID是。是什么呀?是c.ID呗,对不对,哎c.ID啊,就相当于原来是零了,现在呢,给它重新附了一个值,附上值之后呢,接下来我就访问它啊,那最后结果是哎,9521啊来走编译。客户的ID是9521,现在啊,那如果说现在呢,我让这个程序啊。这个C我给它赋一个值,那我再去访问这个c.ID会出什么问题?我再去访问c.ID会出什么问题?就c.ID。
06:00
这里会出什么问题?ID是什么?是实例变量对吧。要想访问这个实例变量。是不是必须得对象存在?C如果等于空代表什么意思?是不是代表这个引用为空了。原先这个C里边保存了一个内存地址,对吗?指向了这个对象是不是。然后你现在C是不是等于空了。C如果等于空了,是不是代表它这个C变量里边保存内存地址了。是不是就好比说大家思考一下啊,就好像你手里呀,有一个气球。然后呢,我用剪刀把你手里的这根线怎么着呢,剪断了之后呢,氢气球怎么着它走了。如果再通过这个C去访问,会出什么问题呢?
07:01
会出什么问题呢?来我们看一下啊,来Java c呢,去编译一下Java去运行,最后结果就是我们所说的non pointer exception。是不是在第16行,这不是编译啊,这是运行错误啊,运行错误出现这个问题了。那么我们这样啊,把这个内存图画一下,各位好吧,一起把这个内存图画一下啊,又画内存图。来我们打开啊,打开之后呢,接下来我们看一下这个内存图啊。嗯,在这儿呢,我们再把这个叫做Java虚拟机画一下,这个呢就是大家想象中的JVM了啊好,那么接下来我们该画的画上去,这个呢是我们的方法去,这个呢是我们的堆是不是,然后这个呢是我们的站啊,然后大概是这样画一下啊,然后这块呢,咱们给它哎去掉啊。好了,那这样的话,这个我们写上这个叫做方法区,方法区然后堆,然后是占是不是哎占然后大家多画图啊,多画图方法区这块呢,会先进行类装载,是不是这个类啊,这个类呀,是不是哎customer这个类啊,System这个类啊,是不是都会装载进来啊。
08:12
会把类装载进来啊,来这个文件我先保存一下。我写上,这叫空指针异常。叫做空指针异常是怎么发生的?那就相当于在这个位置上呢,我们有一个什么呢,叫做。叫做什么呀?哎,String by.class nine pointer test.class system.class.class是不是?哎等等等等代码片段就加载进来了,接下来首先第一个呢,我们问方法执行,问方法执行就会压站呗,所以顺着程序的逻辑往下走就行,不要去越界啊,你不要去越界啊,你说一会儿画画这个,一会儿画画那个,你啥也画不明白啊,来按照程序的执行顺序去画这个呢,其实就是闷方法战争了。
09:02
那么当我们的闷方法战针压进来之后,给这个闷方法分配了空间,分配了空间之后呢?接下来我们先去执行我们第一行代码,第一行代码等号后边先执行你一个customer对象,就相当于这个对象会造出来,并且这个变量会系统负默认值,默认值为零啊,默认值为零啊,那么。那么这个图应该是什么样的,应该是在这个位置上有一个什么呀?有一个对象是不是,哎这个对象呢,就是customer对象啊,叫做customer类型的,叫做类型的对象啊,然后这个类型的对象呢,它里边呢,应该是有一个ID是不是,哎应该是有ID啊,Int类型的ID应该是啊在这写上去还这个int类型的ID啊,值呢,它是多少啊,是零对吧?哎,是零,那么接下来这个对象,整个这个对象啊,它的内存地址。付给谁呢?付给我们的CC在方法当中,它是一个局部变量,这个局部变量应该是在占当中存储,是不是?哎,在占当中存储啊,在这个位置上有一个卡C,然后呢,这个C变量里边保存的是什么呀?这是个变量啊。
10:13
对吧,这个就是C啊是不是,哎,这个就是C,那变量里边保存的是这个对象的内存,就这个整个这个对象啊。这个对象内存地址,比如说0X2345,那么这个0X2345怎么着呢?哎,它就指向谁呢?指向了我们这个对象,就这个啊就这个。这个对象,这个对象啊。嗯,那这个对象呢,我这样,我我再变个颜色啊,我用一下这个。这是个对象啊。蓝色的啊,对象0X2345呢,就是这个对象内存地址。好,那么程序呢,就相当于是到哪了到哪了,到这儿了是不是,哎,这个是不是就直接结束了,这个对象有了吧,对象的内存地址是不是也付给C了,付给C之后呢?接下来我们是不是C变量去保存了一个内存地址指向那个对象。
11:03
是不是?哎,好指向对象,那么接下来说出这个c.idc.adc是谁呀?就是他呗。他们点什么呀,id.ID不就零吗?所以这个位置它会输出零。啊,然后紧接着c.ID等于9521。那9521是C啊C啊点ID是不是它它这块是不是变成了9521啊。谁变成了9521,就这块儿内存空间就不是零了。那就不是零了,就变成9521了,那变成9521之后呢,接下来我们再输出这个位置,是不是就就是c.idc.id是谁呀?不就是9521吗?好,9521输出之后呢,其他C等于空。C等于空,这个等号是负值,是等号右边先执行,那负给了C,那么就意味着nu c这块。没了谁没了各位。这个位置。变成了什么?那。谁变成了呢?
12:00
各位。这边呢。明白吗?这个变成none之后,这个就没了。啊。这就没了。这个啊,没了。这个线没了,嗯。没了啊。这个呢?也没有任何引用去指向它了。你明白吗?啊,这个线断了。嗯。C是个空的引用,不指向这个对象了。好了。这个对象是不是再也没有办法被别人访问了?因为你没有引用,没有引用,没有引用去指向它了。而我们Java程序员又没有权利直接操作堆内存当中的对象,对吧?
13:01
是不是该对象怎么着,该对象没有引用,就是没有引用指向它了。指向他了啊,Java中规定。堆内存。规定什么?堆内存程序员是无权利直接操作的,对吧,无权利直接操作的。此时。此时,这个对象就像氢气球一样。飘走了。啊,等待垃圾回收器的什么回收。GC会将这个垃圾对象收走啊,垃圾对象释放掉。我们认为这样的对象就是我们所说的垃圾对象了。
14:03
啊,因为你再也没有办法被别人访问到了呀。明白吗?啊,就该对象没有引用指向它了。加入中规定的堆内存呢,程序员呀,又没有办法呀,直接干啥呀去操作这个堆。所以这个时候呢。我们呢,这个对象垃圾回收器GC就会检测它是个垃圾对象,垃圾对象呢,它可能就把它哎回收走了,那你再也就防不了了。那访问不到之后呢,接下来这个程序硬要这样访问c.ID首先我们先分析一下这个程序,各位啊。ID这个东西是在哪?是在我们这个对象里边,对吧?那对象都没了,这个ID更不用说了,但为什么编译器没报错呢?因为编译器只是编译检查语法。编译器啊,发现这个CC它的类型是什么呢?是customer customer这个类里边有一个ID,所以从语法角度出发来看,这个符合我们加码语法机制。
15:00
啊,所以编译器就让它通过了,但是运行的时候呢,在真正运行的时候,它这个内存方面进行寻址的时候,它寻到C之候呢,哎,找到这个CC之后啊,诶这是个nu对吧,去找这个ID找不到,那么这个时候呢,就会出现什么呀,叫做空指针异常啊,就出现空异常,所以这个程序大家注意啊,编译没问题,编译器没问题啊,因为编译器只检查什么语法。啊,编译器发现什么C是谁呀。对吧,Customer类型,Customer类型中有ID属性,所以可以什么呀,c.ID啊语法过了。但是什么呢,运行的时候。需要对象的什么存在,但是对象没了啊,尴尬了。
16:04
啊,就只能出现一个异常明白吧,所以就尴尬了啊。就相当于说你放风筝嘛,就跟放风筝一样,大家都放过风筝是不是哎。或者叫纸鸢是不是啊,风筝啊,放风筝呢,风筝在天上飞,你在手里拽,你一拽风筝就动,你一拽风筝就动,那假如说风太大,风筝线断了,那我问你在这里线还有用吗?你再拽这个线还有用没用啊,你拽个线也没有用,没有任何意义啊,你的对象被月老判定成垃圾给回收了,哎,可以这样理解啊,可以这样理解,对这样的话咱们就不会很枯燥了,是不是啊,要不然就特别枯燥啊,也没有什么意思啊,没什么意思。行,就是说可以自己去想象一些别的东西对不对啊,那这样的话呢,有助于咱们这个知识的一个掌握啊掌握那就是C呢,等于。
17:03
等于空之后呢,这根线就断了,断了之后呢,我们再去访问它就不行了。是不是,那大家思考一个问题啊,我们这个如果把它注释掉。这个代码注释掉,为什么会出现控制帧异常?你告诉我为什么,为啥?因为你T扭出来,A扭出来,B扭出来,C扭出来,B扭出来是都扭出来,但是你这个是空对吧,这是不是也是空,这个是不是也是空,这个是不也是空对吧?你这个地方都是空,都是空,那么你将来的t.O1拿的就是A嘛,你这个是空,如果空的东西再继续往后点的话,大家想想是不是会出现空值异常啊。是会出现空值异常啊,对吧?哎,所以说这块呢,我还是要讲到位啊,所以这边我们需要哎给它附上值,你比如说t.OE就t.O1,为了避免它等于呢,我现在呢,通过等号的方式把它A给它附上去了,就相当于这个地方,哎是有值的。啊哎,付一个A过去对吧?哎,那你这个A是谁呀,你在程序里边A就是它拗A个A啊,那就相当于是不是这块拗了一个A呀。
18:05
对吧,因为你A就等于后边这个吗?对吧,那你是不是就相当于t.OE等于A,是不是就意味着这段代码直接拿过来放这了。对吧,你扭了一个A负给了t.OE啊,你t.OE这不就有有东西了吗?有东西你就不会出现什么呀,空指针异常嘛,是不是哎,控制异常。行这个程序呢,你要理解一下啊,这里代码它不写会出现空异常的原因是什么啊,原因是什么,刚才我在这里也讲的非常非常之清楚啊,就这块儿呢,它为什么会出现空制影响,我觉得这个大家也能够理解,你想程序这种东西呃,它不能随便写是不是?哎,那如果是空的话,那么这个对象即将被垃圾回收器回收掉,那么我们没有去引用,去指向它,那就意味着没有人再去访问到它了,没有人再去访问到它,那么我们这个对象就怎么着啊,就被回收掉了啊。被回收掉了。
19:01
另外还有一件事我要重点给大家说一下啊。什么事呢?就是说我们这三个空间当中,垃圾回收器主要针对的是哪个区,垃圾回收器主要针对的是哪个区。各位。注意啊,Java中的。垃圾回收器主要针对的是堆内存啊,Java中的垃圾回收器GC。GC主要针对回收的是堆内存当中的垃圾数据啊,垃圾数据。那什么时候?那么什么时候数据会被垃圾回收器回收呢?垃圾回收器。回收呢?什么时候我们这个数据会被垃圾回收机回收?
20:04
没有什么,没有更多的,就没有再多的。或者叫没有任何引用啊,没有任何引用指向,就没有任何引用指向该对象的时候。这句话怎么理解?没有任何引用指向该对象的时候。我们大家有没有可能会出现这个问题,就是这个地方的指针,虽然这个指向没了,有没有可能在我们程序里面还有一个别的引用。这个引用仍然还是指向这个对象,这个情况存在不存在?有可能对吧。那么像这种情况的话,你这边虽然断了,但是这边有没有可能还没断。这边没断的话,你这个对象是不是就不会被回收啊。所以说我们应该说没有任何引用指向该对象的时候,这个对象才会被被被判定为垃圾啊,被判定为垃圾来这块呢,我也给大家说一下啊。
21:00
关于垃圾回收回收器啊GC在Java语言中,在Java语言中啊呃,在Java中垃圾回收器啊,垃圾回收器。主要针对的是堆内存。啊,当一个Java对象没有任何引用指向该对象的时候。啊,GC会考虑将该垃圾数据释放回收掉。啊,垃圾回收机制不是马上运行的,不过因为你不知道对象所在的内存地址,就没有办法联系上他了,不过如果有他的地址,在回收以前应该还是能用的吧。不过如果有它的地址在回收以前还是能用,对,你只要用一下,它就不是垃圾了啊,你只要再用一下,你稍微用一下,你说现在它已经是垃圾了,但是后来你又用了一下,对不起,那就不叫垃圾了啊,就不叫垃圾了。
22:06
它变成垃圾之后啊,它就回不来了,我说一下啊,它变成垃圾之后就回不来了。啊,你一直在用它就代表它不是垃圾啊,不是垃圾C。还可以重新指向对象吗?C、还可以重新指向对象吗?可以呀,没问题呀。跟C没有半毛钱关系啊,你执行到这个位置说你C等于空,然后C呢,后边又等于一个值对吧,你这个值又拗了一个什么呀?哎,Customer对象没问题,那你拗了个新的对象,就相当于我们C原先啊保存的内存地址啊,指向的是这个对象,如果现在在这拗了一个新的对象之后呢,我们这个C仍然去指向别的对象是可以的。我们并不是说C是垃圾啊,我们说的是我们的这个堆内存当中的对象是一个垃圾。C人家没问题,C可以继续接着用,因为C只是个变量罢了,对吧,变量里边可以存任何类型的啊,可以存很多很多数据,你比如存档也行啊,存这个对象,存我们对象内存地址也可以啊,对吧?哎,都是可以的啊,没有任何问题。
23:04
那么出现空指针,出现空指针异常的前提条件是。是什么?出现空指针异常的前提条件是什么?是空的引用,空引用啊,就是空引用。访问什么呀,访问实例相关的数据啊,访问实例。相关的数据时。都会出现空指针异常,那我说的这句话很深啊,是吧,叫空引用,引用你知道吧?C就是个引用对不对?哎,如果是空引用啊,访问实例相关,或者还有一句话叫对象相关啊,访问对象相关的数据时都会出现空指针异常,好老铁们,我这句话没毛病吧。没毛病吧,对吧,访问什么相关呀,对象相关,你对象空引用就代表你是不是已经不指向对象了,对象是不是是不是已经不指象了,对吧?哎,你是不是访问这个对象相关的数据都会出现空值异常啊对吧?哎,这个应该是没毛病啊,没毛病,大家呢,把那个空值异常这块呢,诶好好理解一下啊,其实我觉得你画图也也能也能画出来啊,画出来另外在这里呢,也稍许的给大家说了一下什么呢?说一下我们这个垃圾回收这个东西,主要是针对于我们的堆内存进行回收,没有任何引用,指向该对象的时候,对象就会被垃圾回收期,诶回收掉啊,给它释放掉,是这样的。
我来说两句