00:00
Hello,大家好,我是上硅谷家外艺学科的讲师柴林燕,今天呢,给大家再分享一道面试题。好,乍一看这道题代码有点多哈,大家可以暂停一下视频,然后呢,来分析一下运行的结果是什么?好,那么我们呢,这个来看一下代码啊,首先这道题其实涉及到的类型呢,有两个,一个是父类跟子类。那么这个负类当中啊,有两个变量啊,需要去初始化,一个是I,一个是J,那么T的方法呢,为这个I进行初始化,也就是说为I初始化时会导致T的方法执行,那么这个为这初始化的时候呢,会导致麦色的方法被执行,同时呢,还会涉及到进的代码块,非金的代码块和构造器啊它的一个这个相应的执行过程,那么此类里面呢,代码结构几乎跟福类是一样的。那么我们在主方法里面呢,就创建两个子类对象,那么它的运行结果会是什么样子的呢?我们先来运行一下,然后再来分析啊,它的这个执行到底是怎么执行的。
01:10
嗯。好在eclipse里面啊,运行一下。好,那么你看一下你刚才推到的结果对不对呢?如果对的,我们一起来看看咱们的分析过程是不是一样的,如果是不对的,看一下哪步你没有考虑到呢?好,我们来这个分析一下啊,其实这里虽然代码很多啊,那么考点呢,其实一共有三个来着,一个是类初始化的过程。那我们就要思考了,什么情况下会导致率出始化?以及类出化过程做了什么事?还有一个就是实例初化的过程,那么什么情况会导致实例初始化,以及他又做了哪些事情呢?第三个这里还考虑一个方法重写,也就这有个坑。那么我们要看什么情况下会有方法重写,对吧,什么情况需要考虑这个东西。
02:03
那么我们一点一点来分析,先看类初始化过程,那么想什么情况会导致类初始化呢?我们都知道创建一个实例对象时,会需要加载并初始化这个类型,也就是说我们看这个代码的话,对吧,觉得哎,我要用这个上对象了,那么就要去初始化这类,但其实啊,这里呢,我们要注意。有一点非常特殊,主方法所在类它会先去啊这个加载个初始化。当然这里并不冲突啊,因为我这个主方法也是在丧类里面,所以不管你是有丧对象,还是因为主方法的问题,它都会导致丧类出手。啊,那你看一下,比如假设我把这个这三句代码删掉,它仍然是会导致我没写初始化代码执行,那你先不管这个结果怎么样,但总之它导致一些代码执行说明啊,这个有些代码会发生是吧,代码之会发生,因此我先撤回来啊,这当中。
03:02
因此呢,我们要注意啊,这个累初始画一个呢,是因为你用它对象了,一个呢,就算你不虐它对象,总方法组它累,它会先在初始化。那么大家呢,这个要看啊,什么情况发生类出始化,这是咱们经常遇到两种情况,然后呢,我们这个还有一个问题,因为这里的子类丧类,它初始化的时候还会导致父类初始化,那我们知道有我们的前提得先用我们的父母,所以说我们子类初始化得先用父类。因此这个当中啊,我们就会注意了丧类彗星初始化,但是因为它有负类,负类也没有初始化,那么这个时候会导致负类的初始化,那么第三个问题,初始化都发生了什么事,对吧?好,这里提到了一个CL方法解,就class initial类始化的方法,每一个类都有这个方法。有的人说我这个代码当中没看到这个方法呀,是吧,我也没说去这个执行这个方法,对这个方法呢,不是我们来编写的,是编译器帮我们去生成的,它在自检文件当中能够看得到啊,那我们这个里面呢。
04:09
找到我们的这个子件码,好找到这个当中,那么这里呢,我们需要借助一个插件来查看,那么这个当中C包括三类也有这个的,每一个类都是有这个,你会以后呢,你看每一个字节码都有这样对应的方法,这个叫做类出手环方法,那它由什么来组成的呢?是吧,它这虚拟机帮我们这个生成这个方法的时候,它要把我们哪些代码放到这个方法里面去执行了。哎,这里呢,就说它有一个静态的内变量。静态代码块来进行组成。那么这两个呢,就是谁在上面谁先执行。按顺序执行。并且。只执行一次。只经一次。
05:01
这是他特点。好,我们来看分析一下啊,回到我们刚才这个代码当中,比如说我把这个再删掉啊,我们来看一看,对吧,它执行了对吧,类出什么,那我们看这个过程是怎么来的,分析一下。好,这里面呢,就要分析了,我们说了要初始化之类,对吧,初始化。初始化此类,那么我们会先初始化负类,那么这里面呢,哎,负类初始化是什么事呢?就是负类的初始化,那么执行该是我们刚才说的这个方法呀,那么它由什么组成的呢?两部分组成第一部分。静态类变量的显示复制代码和静态代码,并且是按顺序好了,那我们过来静态就这个了,声明不包括啊,我们说的是显示负值,好,然后呢,第二个金单蛋板块,那么我们叫负类啊金台大码块。
06:14
子类的这个也有,这个子类的初始化也一样。两部分组成第一部分子类的,然后呢,子类的静态判的谁先执行,肯定先执行它,那么也就是说我们呢,会。执行的是这个method。好,那么这里method的代码我们看一下五对吧。然后呢,负类的静态代码块。那么我们这里呢,是一子类,那么卖的方法执行的是十,然后呢子类的。
07:02
简单大板块六好,我们来看一下运行五一十六对吧,也就是你如果仅仅发生类出手话,不发生实力水化,那么就是这样的一个过程。就是用那个,那么我们这个当中代码还没完呀,是吧,哎,我们呢,还有这样的这个子类呀的实例数字化呀,好,我们刚才这个代码呢,我考原一下啊好,然后呢,在这个下面又创建了一个第二个对象。那么这个时候呢,除了类数的话,后面还得有别的。那么说什么呢?哎,看一下下面的话就是实例数始化,实例助手化,那做什么事呢?哎,这里呢说实例数化执行的是这样的一个方法,好比刚才那个呢,少了CL,因为CL代表class类出,那这里没有这个,那就实例触划方法,那么看看自建码当中啊,其实有这个来着,因为我刚才那个写的注释,所以它重新编以后啊,那么我的字页码重新加载一下,那没关系啊,结果不影响这个排好,那么丧里面也有这个找对应的it方法,实际说。
08:19
那么我们这个又是怎么样子的呢?他呢,有可能有多个,跟刚才的类数法不一样,类数完一个类就一个,这个呢,有可能多个,有几个波导体就有几个这个来着,那么我们呢,因为它有可能有参的无参的对吧,它有什么组成呢?注意啊,肥静态。变量的显示、数字化代码和非静态代码块以及对应的构造器代码。那么这个当中啊,我们。顺序,他们谁在上面,谁在进行勾到气,最后执行。而且。他们的每拗一次对象。当它调用对应的构造器的时候,就会导致对应的这个来。
09:03
这些。好,这里呢,还有一条啊,就是我们呢,就是除了我们刚才说的这三部分组成之外。还有可能会有这个。S,也就是说我们这个里面啊,之前讲的时候,继承的时候对吧,我们加当中继承的时候说子类的构造器里面一定会有啊这样的一句一句就是他写或不写都是存在的,也就是说在此类构造器中一定会调用负类的构造器,负类构造器。一定会调用它,那么因此我们呢。什么意思呢?哎,就是我们接下来就是子类的实例出发,那么它的构成就是由这一部分组成的,第一注意啊,这个一定是带首行。
10:00
在首行,然后我们呢是非静态变量,然后是非静态代码块。子类的,这好第四个。就是子类的无偿构造。注意啊,勾到起是在最后,他一定是最后,这个是一定是最前。然后呢,这个呢,这两个呢,按顺序。中间两个顺序。好,那么这个相当于是负类的了。那负类的这个它其实也是一样的负类的。这个当中呢,就是负类,当然这个呢,因为我们有一个默认的object,那么它就导致那个,那因为那个没有打印,所以看不出来效果。好,那么这个当中呢,就是负类的,这款负类的。
11:02
整个的四部分组成。好,那么这里的话,我们来看一下它的运行过程是什么样,按理说那么这个so啊so,注意它就代表的是整个的这个了,那么我们是不是I等于test test哦,那一看。应该是不是四呢。但是它不是,为什么这里呢,还涉及到一个点,就是我们的方法的重写的问题,那为什么刚才我们在讲这个类数法的时候,Method我们没有讲这个重写呢?你看我们这个里面是吧,有同学说,那你此类说就讨论这个,呃,非静态的这个test讨论这个重写,那你这个method怎么没有讨论呢?好,那么这里就要说一下啊,哪些方法不会被重写?对吧,然后呢,我们这里为什么会啊,这个涉及到重写的问题,我们有个对象多态性。那么也就是说我们什么叫对象的多态性,对吧,就是我们这个当中啊,这个非静态方法。
12:07
方法前面起始对吧,前面起始有一个默认的对象就是this,那么这个this啊,This,那么在我们的构造器啊,或者说我们现在说的这个init方法里面,实例出始化方法里面,那么它表示的是正在创建的对象。那正在穿越对象,那么我们这里,因为因为这里啊,因为这里是在创建子类对象,所以啊,那么我们的这个test,那么执行的执行的是子类重写的代码,这是我们面向对象的多态,面向对象多态的这样的一个原则,对吧,重下代码,因此这里test啊,这里I等于test执行的是子类的重写的test的方法代码。
13:16
好,所以说这个当中啊,我们呢,就会是这样子了,这个我们就导致了。第一句啊,它代表这这些嘛,第一句这个它就没什么效果,那我们就从这儿看test test,那么它咱写的是子类的,这个子类test呢,就是九,因此这句话的话,那么执行的话,我们就是九。完事以后,那么就是负类的非静态大板块。飞进的那么块,那我们看一下是三,那么负类的勾到T,那么就是二。932,那么这个I的T,那么就本类的类了,那么就是九,然后呢,这个地方呢,飞进的代码块那么八,然后呢就是七七。
14:03
好,还有一点,我们刚才说到了一个问题啊,就是我们的说啊,就是。每一个穿在谁对象都会导入这个,那么我们这个里面啊,我来啊。先切换回来啊,那么也就是说我们这个实一说法方法发生两次,因为创建了创建了两个上对象上对象,因此啊,那么实例初始化的这个方法,就这个方法它执行了两遍,因此啊实例初始化。方法执行了两遍。执行两次,所以呢,我们的最终的结果呢,就是。这个又执行了一遍,987又执行了一遍,又执行一遍。
15:09
那么这就是我们最终的一个结果。9329排七,9329排七好,那么这里呢,我们为什么method的没那个呢?我们来探讨一下啊,这里我们说的method的方法这个是。的静态方法。属于我们不被重写的方法之一。我们不被重写方法有final。还有在此里不可见的,还有就是一个静态方法比较特殊,它不能被重写。所以说我们method的方法是没有考虑这个,而我们test方法就不一样了。那么对象多态性刚才说了,那么就是我们这个子类如果重写了复理方法,通过子类的对象,那么调用的一定是子类重写单位,那么因为我们这个啊法默认调用对象是this,这里在这个勾造器或者ID方法当中,就正在穿越对象就是this当前对象。
16:03
所以我们的这个啊,考点有三个来着,一个是例初始化过程,第二个实例除法过程,第三个就是关于方法的重写,哪些方法不会被重写,哪些方法会被重写好,那么这里呢,我们再给大家呢,来变化一下,怎么变化呢?好,我们刚才在这里说到啊,这个代码是顺序执行。我们来换一下位置,什么意思呢?比如说这个静态的,我挪到了这个下面它两个。换了一下位置,那么你看一下它的结果会不一样。运行。你看它这个就是一在前面,我在后面,你看我们刚才这个是五一嘛,那原因是因为他俩的顺序可以换,谁在上面就在下面撤回来。同样的道理,这个也是一样的,这个跟比如说他俩的顺序,你看我们构造器虽然在上面,但是我们的这个啊,非个非批量代码块和这个啊,那么它俩的顺序也是有顺序的,那你看一下运行。
17:17
那么这个当中,你看这个三三是怎么回事呢?对吧?三,那么就是他先执行,然后呢九,那是因为它执行的重写的九,然后再执行的是这个二。所以说我们啊,这个当中,我们把它再扯回来哈,也就是说我们这个里面记住啊,这两部分代码是顺直行的,还有这两部分代码也是顺序执行的。飞进来的那那个显示数的话和评价代码,那构造器的一定是在最后,不管你写在哪,都在最后,然后so呢,是在最前。这个呢要总结一下。那么如果像大家想要这个,遇到这个类似的这样的点啊,除了那个呢,我们还希望大家能够扩展开来,比如说像跟重写有关系的重载呀,也不是有关系,因为他俩比较接近啊,就容易搞混的,那么大家要自己总结一下,还有重写的要求,对吧?你要判定哪些方法是属于重写的,哪些方法不是重写,你就要看他的要求,是只有满足对应的要求,他才能去重写。
18:22
对,那么大家可以总结一下,那么如果对这个呃。两个方法,有兴趣的同学可以看一下虚拟规范当中关于它的说明,以及他这个调用的一些指令啊,一个special。好,那么今天呢,就讲到这里,那么谢谢大家。
我来说两句