00:00
那下边呢,咱们一鼓作气来说一下关于这个被动使用的这个场景,被动使用呢,咱们说到了就是不会去进行初始化DG呢,就不会去调用那个C2D的这个方法了,对吧,主要这个场景的话呢,这里边列举出来了这个四个点啊,CTRLCL一下,咱们来做一个这个验证。那关于我们这个JAVA1这个包,咱们去新建一个class,这个呢,就称为呢叫passive。Passive use啊一对吧,这呢就关于类的被动使用。这个类的被动使用,即不会这个进行类的一个初始化操作。啊,其一啊,不会调用这个C2的方法对吧。好,那这呢,我们一共提到了有这样的这个四种情况。那我们一一呢来进行一个说明,首先呢,第一个说,当访问一个静态字段的时候,只有真正声明这个字段的类才会被初始化。
01:01
当呃,比如说一个主要的这个场景,就是当我们通过这个子类呢,去引用父类的这个静态变量的时候呢,不会导致这个子类的一个初始化,这个呢是非常典型的一个场景,比如这块呢,我们去声明一个,嗯,咱们称为呢叫parent吧。这是一个类里边呢,我们去加上一个静态代码块。Parent的初始化过程。行,然后接下来的话呢,我们在当前这个复类中,咱们再去声明一个叫比如public的啊,Static啊,我定一个int型的一个number啊复制,比如说是一。接着去提供这个parent,它的一个子类,这个我们叫child,去extend parent。好,对于我们这个此类的话呢,咱们也加上一个静态代码块。哎,Child,它的一个初始化过程。OK了对吧,行,那下面呢,咱们来做这个测试,这呢我使用这个比如单人测试方法。
02:00
我们呢,通过这个child。哎,点我去点一下这个父类中的这个number。你看点负类中这个number,那点负类中这个number的话呢,现在就要提到我们会去初始化这个负类,但是我们这个子类的话呢,就没有初始化了,跑一下。你看很显然是吧,我们这时候呢,这个父类它执行了,子类这个没执行,所以呢,子类没有初始化,注意子类没有初始化,那我们子类加载了吗。那这里边儿我们要强调一下说明。说明这个没有初始化,初始化的这一类啊,不意味着。没有加载啊加载。就是加载初始化是我们说的这个先后的几个过程啊这个呃,我们来验证这个问题的话呢,也比较简单,咱们刚才呢,是不是提到一个参数的问题,对吧。Edit,咱们刚才在这个G当中,在这咱们加上一个参数,那我们把这个参数呢,再给它加上。
03:05
啊,就是class loading这样个参数。诶,CTRLC一下,那我们在这个下篇当中啊,咱们就系统性的给大家把这个参数啊,到时候都讲讲上面呢,其实咱们也讲过对吧,关于这个垃圾回收啊,设置这个,呃,我们内存中相关的一些结构的这个比例啊,咱们都讲过这个参数,但是我们没有系统的去说,比如这个参数的怎么个方式去设置这个,到时候咱们下篇呢,都带着大家再讲一讲。好吧,行,那这呢,我们就先放到这儿,然后下边呢,我们做一个apply应用啊,做OK啊,我们再把它跑起来。OK了,那最后呢,我们确实还是看到了,只执行了这个负类中的这个结构,对吧,哎,Ctrl a ctrl c,把它来粘出来,我们放在这。啊,看到这了啊,大家看到这儿的话呢,我们上面也能紧接着看到这个parent这个类呢,被都对了,就加载了child呢,其实也加载了,只不过呢,它没有初始化啊这个注意一下。
04:01
行,这呢是我们说的这个第一个场景,那这个场景呢,我们见的比较多啊,大家呢,稍微留意一下,说下边呢,说通过这个数组去定义类的引用的时候呢,不会触发此类的一个输入法。啊,这个说的是这个意思。托尔斯泰就出来了啊,那这个时候呢,比如说我们去创建一个father,诶father了parent吧。T类型的一个数组。哎,Parent啊,你有一个parent数组,哎长比如V10对吧,那我们创建这个数组只是声明了一个数组,那此时的话呢,我们做一个执行。嗯,这时候看到有点多,咱们把这个再去了吧。嗯,把这个删了。好,重新的再执行。OK了,那这时候大家会发现呢,你看没有任何的输出对吧?啊没有输出呢,就意味着我们此时这个T的这个类呢,是没有初始化的,同样问题加载了吗。
05:08
那是不是得加载一下OK是吧,哎,这呢就没有初始化啊,那这呢算也是一个类型,那这个类型实际上呢,我们说在运行的时候呢,它才会帮我们把这个类呢给它加载进来。啊,把这个类加载加载进来,你看此时如果我们要去打印一下这个parents.get class啊,获取它所属的这个类,啊,实际上呢,就是parent构成的一个数组,对吧。那这个parent构成的一个数组对吧,那这个类的这个父类是谁呢。Get一个super class。那其实我们说这个数组类,其实它的负类呢,默认情况下呢,也是object。啊,没问题是吧,那这个大家了解一下就行,OK,那这个时候呢,咱们没有进行一个初始化,什么时候会进行初始化呢?就是我们给比如说这个数组具体的索引为零的位置,咱们做一个new了,只要一扭是不是就涉及到这个出入法的问题了。
06:02
咱们将主动使用的时候呢,这不就说过这个问题是吧,那是在我们这个输入语的后面,相当于是你在这块new的时候呢,才触发的这样一个行为啊,这个呢就不用多说了,就是关于我们这个类的一个初始化的话呢,是指在你new的时候才触发的。能行是吧,那我再写一句呢,我写个一再拗一下,还会再出发吗?显然是不是不会呀,那就是我们所说的这个CR这样一个类构造题方法是不是只会执行一次啊,哎,这要注意啊,行,这呢是我们说的这个第二个这个情况,第三个呢,说引用常量不会触发此类或者接口的一个初始化,那因为常量在连线阶段就已经被储值了,呃,这个呢,其实在咱们讲那个主动使用的时候呢,咱们其实提到过这个问题是吧。啊,咱们再去新建一个。Passive又是二。
07:01
好这个三跟四,那来咱们进行一个这个测试。哎,这样一下,那这里说的是这个意思,说引用常量呢,不会触发这个类或者接口的一个出入化,嗯,咱们先整一个类吧,比如说这块user,我写成一个,比如叫person类,这个类里边我们声明了叫public static final啊,Int型的叫number啊,这是一。那这个加一个静态代码块。Person这个类的初始化。哎,好是吧,然后这时候呢,我们去调用一下你这个person.number啊做一个输出,那咱们说到了,你要是不加这个final的话啊,不加这个final的话呢,我们做个执行,那显然呢,是不是会触发person的一个输入法,对吧?那这个呢,咱们刚才已经讲过了,当我们这块加上这个final之后,诶。
08:05
这个时候呢,我们再执行。此时的话呢,就不会初始化了。那其实这时候呢,大家再去想也好理解,为什么呢,我们这个一的话呢,是不是在这个叫嗯准备环节就已经被复制了,在这个链接过程的准备环节就被赋值为一了,是吧?那既然呢,你那时候已经赋值为一了,那我们这时候再去调number也用不着我去调这个初始化了,因为这个一已经附上了吗?那既然不用初始化,那我们就不会去调这个c in,当然也就不会有这个输入语句了嘛。对吧,哎,因为我们这个说来一遍了,这个语句是不是写在c in里了,哎,我们这块你看一下这个过程,这打开c in code里边,这不就这个初始化这个语句吗,是吧。好,这呢是我们说的这个意思,当然了,咱们其实在讲主动使用的时候,把这个事儿也都已经说的挺透了啊呃,如果我们这个位置我写的是new,一个a random。
09:04
嗯,第二。再唠叨一遍啊,写一个他这个叫NUMBER1,那问我这时候改成叫NUMBER1了。对吧,把上面的注释一下,那这个操作呢,会触发这个当前类的初始化吗。哎,大家呢,可以恢复一下。那这个我得把它先删了。这时候的话呢,是不是你这个赋值操作,你看啊,我现在呢,做一个re compile编译。然后呢,我们过来这块刷新一下啊,明显你看这个CR里边的代码量更大了,多了哪呢,是不是就多了这块操作了,这块操作呢,是不是就是给我们这个NUMBER1这个值进行了一个负值啊,那我现在想去调NUMBER1,那这个值呢,不就得调它吗?要想调它你是不是得执行这个c in呀,那就意味着调CL unit不就意味着当前这个类的一个初始化吗。所以呢,是不是就执行了呀。
10:01
哎,这个就一脉相承的,咱们前面的不也都是这样来讲的嘛,是吧。好,那这呢,咱们举的是关于这个叫类的啊,当然这时候这个常量呢,咱们你就按照我讲的那个来说啊,这块呢,咱就没办法写的那么细致啊,一点一点的说的那么透彻了啊,领会精神啊,那这个接口的话呢,说引用常量接口也不会,其实咱们那会儿也见到了这个interface,我叫比如zero a。啊,这个接口里边咱们还可以类似呢,使用刚才这样一个套路啊,来验证一下你这个接口呢,是不是做过这个除入法。回过来粘过来,把它CTRLC。哎,我这样一下对吧,行,然后在这里边呢,咱们其实跟类似这样的一个场景,嗯,他这个study默认它其实就是我就直接写一个,比如ID啊,是一个一。那这块。单元测试方法。行,那我们通过这个CA。
11:03
第二咱们去输出它这个ID,嗯,这样子对吧,那此时的话呢,我们要执行是不是照样的也不会去。这个初始化,咱们当前这个接口。啊,也不会的是吧,那什么时候就会呢,咱们跟上面那个NUMBER1是不是一样的道理啊,哎,我这样写的话看CTRLC。这样子对吧,那这样写的话呢,就IDE,那我把这个呢,就铺这一份上面这个注入调改成IDE1,那此时的话呢,是不是就会触发呀。原理呢,是一样的。你看这就出发了是吧,那原理是一样子的啊,就是因为我们要获取这个值的话呢,此时的这个值我们只有在这个类的构造器方法当中,咱们才可以呢去调用这个结构,那因为你想这是一个具体的代码的执行了嘛,那这个代码的执行要想执行,那你得写到CR里边啊,所以我们这里边写说此时的这个复制操作需要呢,在。
12:00
哎,需要在这个c in这个方法中这个执行,那既然在这需要执行,那你自然而然的就需要呢,去初始化嘛,那下面这个是不是也同样的道理。也没问题是吧,好这个呢,就是我们说的这个第三个点。然后看一下这个第四个点说调用class loader的叫load class方法加载一个类,不会呢,对这个类呢,进行主动的一个使用,那也就不会呢,做一个初化。那这个呢,也是咱们下一章咱们要讲这个类的加载器和类的这个自定义类的加载器。那这个时候呢,我们会讲到这个load class这样一个方法,那我们去加载类的话呢,除了咱们使用这叫class.for name之外,还可以使用呢,叫class load是吧?第二比如说我们get叫system class,第二我们叫load class,加载谁呢?加载咱们这个person吧。哎,我这块呢,去copy copy一下它的reference,诶CRV啊粘过来行,那本身的话呢,由于你这个权利名你有可能写的不对,所以它呢会抛个异常对吧,我们这呢做一个check catch。
13:05
那可以了,那这时候呢,他会得到一个具体的一个class。嗯,这是没有问题的,那此时的这种方式,我们如果去加载一个类就不会呢,呃,调用这个C。你看这是没有对吧,哎,我们这句话呢,没执行嘛,跟咱们刚才说的这个主动使用。主动使用找一下应该是写到这儿了,主动使用的话呢,我们这是不是写诶没在这写在在哪下一个。下一个我们这个呢,叫主动使用,就是通过class for name,这叫主动使用,而我们现在呢,使用这个class loader点啊load class这个方式呢啊,这个呢属于一个叫被动使用啊,这是反射里边呢,这两个点的一个区别。行,那么关于这个被动引用呢,咱们就也介绍到这儿了。那就介绍到这儿,这儿呢,呃,稍微有一点难度,也是咱们这一章里边的这个,嗯,比较难的这个两个点之一啊,另外一个点呢,就是关于我们哪些操作在准备阶段,哪些操作呢,是在初始化阶段进行的那个显示赋值对吧?好,那这呢我们就说清楚了。
我来说两句