00:00
那接着话呢,我们继续往下看啊,下边这块呢,是一个了解的内容,一个呢叫做类的加载过程,另外一个呢,叫做类的加载器啊这两个内容呢,是了解性的,咱们熟悉熟悉呢就可以了,那首先呢,我们来说这个第一个问题叫类的一个加载过程。啊,原来的时候呢,我们像第一天的写了代码,光讲过这个事儿啊说呢,我们编译以后生成的叫自解码文件了,然后通过呢,java.es这个命令呢,咱们把这个对应的自建码文件呢,就加载到内存里了。哎,到了内存了,咱们就可以呢,直接呢去使用,比如说我们把P类呢,加载到内存里以后,里边呢,就构造器,咱们就直接在new后边加个构造器来造个对象了。那至于说呢,把它加载到内存中的这个过程的细节是什么呀,咱们是没有细讲的啊,我们呢现在呢,就想稍微的说一下这个事儿,这儿呢,注意也只是一个了解啊,详细的这个内容的话呢,在GM当中都有讲解。好,那既然呢,说到这个事儿呢,我们也简单的看这样的一个图,OK啊。
01:00
好,这个图的话呢,我们就还是使用这个叫process on了啊哎,回过来这呢,我们就找一下这个GM了,哎,这个上篇里边的,哎,简单的我们就先看一下这个图吧。这个图的话呢,就是我们前面也看过的啊,就是我们说这个扎va虚拟机的整个这样一个架构图了,Java虚拟机从哪一块开始呢?诶我们注意呢,就是从这块开始,往后边这块呢,都算是虚拟机的这个东西了。哎,那么你能看到这个入口这块呢,需要打交道的叫做子解码文件,也是我们所谓的点class文件了,诶首先呢,使用叫类的加载器,然后呢,把相应的这些子解码文件呢,不就加载到内存里了,咱们说呢,如果你要这是一个类的话呢,不就把它放到这个方法区了吗。哎,就是这样的一个思路啊好,那么这里呢,就提到一个类的加载器了,那具体来讲把它展开来说一下,这个我们就可以看后边这个图。嗯,看这个英文的吧。这呢就是我们所谓的叫类加载器子系统里边的相关的这个内容,那么类的加载过程是什么样的呢?这块我们可以说呢,有三个大的过程,第一个呢叫做loading,第二呢叫做linking,第三个呢叫initialization。
02:04
翻译过来呢,这叫。这个按说呢叫加载是吧,但是整个这个事儿呢,我们都称为呢叫类的加载了,所以呢,呃,整个呢叫类的加载,它也叫加载就分不出来了,咱们换一个词吧,比如这个叫装载。啊,这叫装载,这个呢叫链接,这个呢叫初始化。所以大块呢,是有三个环节啊,依次递进,那初始化完成以后呢,这个类呢,我们就认为呢,它就加载到我们这个相应的这个方法区里了啊。好,那么在这个链接这个环节里面呢,又分成了三个子步骤,分别对应的叫verify prepare和这个呢叫验证,这个叫准备,这个叫解析。啊,那么下边我们可能要关心一点,就是到底这里边儿的大的环节一啊,环节二环节三都干什么,这里边儿又分成了这个2.1 2.2 2.3,他们到底都做什么的。稍微的我们了解一下啊,这儿呢,我们就先就是咱们现在要讲的,其实就这里边的这个结构了啊,把它呢,我们这块盯一下啊,往这放一下啊,好收起来好这个过程一就咱们刚才说的第一个啊,我们称为它叫类的一个装载。
03:13
哎,这个装载对应的英文呢,我们刚才看到了叫做loading啊。哎,这样的一个环节,好,那么这个环节都做什么事呢?我们在课件里边呢,这块有写。啊,这个类的一个加载过程。嗯,OK啊,它呢就做这个事儿,我把它那CTRLC咱们直接粘过来,说呢,将类的class文件呢读入内存,并为之创建一个Java点浪点class的一个对象,哎,此过程由类的加载器完成。哎,这个看大家能看懂吧。诶咱们说呢,把这个呃大的class,诶把这个先说这个吧,把我们这个词解码文件。诶把它呢,加载到我们这个内存中是吧,生成一个大的class这样一个实例,你会发现呢,诶第一个环节就把这个事儿呢,基本上就做了。啊,就是已经呢,通过类的装载以后,我们就有一个大的class的一个实力了。
04:05
啊,这呢就说的这个事儿啊,然后这呢,咱们只是拿这个类来说的啊,那其实呢,你这个接口啊,数组啊也类似的这样道理,这个呢就称为呢叫类的一个装载,哎,大家需要记住的就是在装载完以后,咱们就有了这个大的class的实力了。啊,这是第一个事儿啊,然后第二个过程呢,我们说呢叫链接。用这个吧,链接它呢,对应的呢,我们叫a link。哎,这样一个环节,然后它呢,具体的又分成了这样的几个子环节,第一个呢,我们称它叫做验证。啊,这个验证呢,对应这个词呢,叫verify。啊,第二呢,我们称为它叫做准备。这个呢,叫。哎,第三个呢,我们叫做这个解析。Resolve。OK啊,那么验证啊,其实呢,就做相关的一些检查了啊,具体来说啊,就是这里边儿有这样一个情况啊,CTRLC啊粘过来,那么确保加载的类的信息啊,符合GM的规范啊,比如说我们都得呢,以叫CA baby开头啊,没有安全方面的问题。
05:12
叫咖啡宝贝是吧?啊,这个什么意思呢,咱们呢,随便呢,找一个点class文件啊随便找。哎,我这就挺随便的啊,好把这个呢,比如说我们先回到咱们的。收印吧。嗯,在这呢是吧,这呢就是个自行码文件了啊,这个自行码文件的话呢,哎,比如说我这使用一个,哎,这个叫notpad加加了啊,哎,我使用它呢去打开,这时候大家可能会发现呢,这不是跟乱码一样。哎,大家也会这样啊,哎,我这儿呢,装了一个插件啊,这个插件呢,就是使用这个16进制呢,去查看的啊来我们点一下。哎,这呢,就呈现出来都是十九十六进制了啊,然后呢,你会发现啊,我们这个开头呢,哎,就是叫cafe baby嘛。
06:02
是吧?哎,就是咖啡宝贝是吧,诶其实它这个开头呢,我们把它那还起个名,这个呢,就叫做魔术啊。不是魔术,是魔术。这个这个,诶这个这个数,数学的数。啊,魔术。就他行,也就是呢,我们这个只要是呢,是Java能够识别的这个磁解码文件呢,它都是以这个CACBB开头的。随便找一个都是这样子的啊,这个我是使用的这样一个呃工具来查看的,呃或者的话呢,我这不还有其他的一些工具吗。嗯,比如说呢,像。哎,这个。啊,Baryver啊,大家如果想装,你去网上下一个都行啊。嗯,把它呢整过来,然后呢,我把这往这一拖啊,这样也一样啊,都能看,这不也是开吗。啊,没问题是吧,随便你找个自行码文件都是如此,那这这个呢,我们就相当于是做一个校验了。啊,校验的话呢,你看是不是这个开头,不是这个开头的话呢,你肯定不是一个合法的一个自解码文件哈,诶类似的话呢,还有其他的一些校验啊,这常就是一个验证的一个过程,看看你当前的四机R文件呢,是不是合法。
07:09
OK啊啊,其实大家呢,你会发现呢,比如说我们这个点GPG。是吧,这个叫图片了啊,假如你有好多的这个啊假GP文件,你呢,也可以考虑呢,使用这个刚才我用的这个notpad加加你去打开,你看一看,他们其实开头的一些这个数字呢,也都是一样的,都会有一些格式的要求,是吧,通过这个一开头这些数字呢,就来验证你是不是一个这种合法格式的一个文件了啊。好,这是我们第一个环节了解一下,第二个环节呢叫做准备,准备呢叫prepare啊,准备是干什么呢。哎,做这个事儿,CTRLC一下。啊,大家看啊说呢,正是为类变量分配内存,并设置类变量的默认初始化值的这样一个阶段,这些内存呢,将在方法群中进行分配。说的直白一点,就是给我们的静态变量。分配初始化值。
08:00
哎,注意分配初始化值。这呢是一个准备环节,那涉及到过实例变量吗?没有,你实例变量是不是随着对象的创建才加载是吧?啊这个时候的话呢,我才会给你去考虑赋值的啊,咱们现在的话呢,是在考虑类的加载过程,所以呢,我们只会涉及到类变量,而且呢,这个环节你注意根本不涉及到显示赋值啊,只有默认赋值。哎,这个注意一下,这个呢是叫准备环节啊,哎,相对来说也比较好理解,下边这个解析的话呢,就会有点难度了,解析做什么呢?哎,解析做的是这个事儿。哎,把这个呢,我们拿过来发呢,虚拟机说常量池内的这个伏二引用啊,伏二明会替换为直接引用啊,一个地址的一个过程。哎,这个大家呢,就会发现里边有两个词,第一个呢叫符号引用,第二呢叫做直接引用是吧?啊就可能有点懵了啊,说这是什么意思啊啊,你比如说我们刚才呢,举例的这个是吧,这个话呢,咱们如果使用啊,其实我这块我双击就行哈。
09:00
双击这块呢,相当于我是使用的叫back VIVO这样的一个客户端来打开的啊,这个大家其实也并不陌生,咱们在这个idea当中呢,诶不是用的这样的一个插件嘛,是吧。啊,那这块我是随便找的,那咱们就还拿这个product product来说事吧,咱们这块就不在这看了。这是第11章是吧。哎,既然说到它了,那咱还就拿它来说啊,我呢就把这个类呢给打开了,打开以后的话呢,这么着啊,我这儿呢,这就可以view是不是可以查看了。查看的时候呢,咱们现在这个叫做解析啊,这个环节什么意思啊,诶大家可以这样去理解哈,诶我们把这个呢,打开以后,你会发现呢,这里边儿呢,有很多的这种常量的信息。哎,像这里边儿这个01020304啊等等等等等,这呢就是一些常量池的一些信息了,它前边的这个标号呢,咱们可以理解成呢,就是一个符号的引用。就是一个符号了是吧,然后呢,具体的我们现在已经把整个这个所谓的这个类啊,咱们加载到内存里了。
10:03
那加到内存里了,那么就有相应的位置,是不是要放这些数据啊。那么这时候再放的时候呢,我们就不能再用这个虚拟的这样的一个值了。啊,你比如我们,我随便挑一个这个位置吧。你看这个位置的话呢,它写着说,诶我们这个呢,是一个class哈,它呢又指向的是这个67,这个67呢,你就这块去找这67。哎,这不就找到这儿了吗?诶这个67呢,其实对应的就是我们后边这个数据,你看这不就它吗。啊,就相当于呢,我们这里边儿呢,相互之间呢,大家也会去引用,那么在我们这个自检码文件的角度呢,咱们引用的这块,你说引用的是谁啊。呃,就像我们刚才那个位置一样啊,诶这块呢,引用的它就是71,这都属于符号引用了,但是真正当你放到内存中的时候呢,我们要把这些符号呢,替换成你真正的一个内存的地址了。啊,你比如说这个位置呢,你就不能写67了,呃,不能写71了,应该写你真实的,你要引用的那个71,他在内存到哪个位置,这个呢,就替换为那个真实的一个地址了。
11:01
所以呢,就理解为是我们所说的哈,要把要把这个叫符号引用,刚才看到那一串数呢,换成一个真实的一个内存地址了,这就叫做直接引用一个过程。啊,这呢叫做解析。OK啊,这个呢,稍微的不太好理解。好,这个完了以后呢,最后一个环节呢,叫做initialization哎,我们称为它叫初始化。这个稍微的难写一点啊,一呢是。嗯。来C是吧,诶这样的一个环节啊,好,它呢叫做这个初始化环节,初始化环节要做什么事呢?回过来啊,你看这块稍微的有点长啊,来我们把这个事儿呢,CTRLC一下粘过来。哎,稍微的长一些。哎,这里边还出现了一个我们不太熟的一个结构啊,用在这个初始化的这个过程啊,其实就是执行一个方法的过程,这个方法呢,称为叫类构造器方法这个过程,这个呢,以前我们没怎么提过这个概念。
12:01
这个呢叫做C。哎,我说的是没怎么提过,应该我稍微提过一下,但是提的频率呢是极低的哈,这个类构造器方法呢,注意它呢是由编译器自动收集类的所有的类变量的赋值动作,你可以理解成了叫显示赋值和那静态代码空中的语句呢合并构成的。我前面呢,提到过一下这个点,但是呢,我就一战而过了啊,咱们这块呢,稍微的我再提一下啊,比如说呢,我们就还在这个里边,咱们做个了解就行,哎,我这儿呢,比如说整一个类呢,叫做order吧。这是一个类啊,这个类的话呢,我们呢,会去声明它的一个静态的一个属性,比如说int型的。哎,我们叫order的一个描述吧。啊,这呢是我清明成一个int类型了啊诶然后的话呢,我这呢显示比如附了一个直角一,咱们呢,也可以在这个静态代码块里边呢,给它附一个值。哎,比如说这个值呢,我改成12了,好,那么这个结构呢,我们去加载这个order类的时候啊,回忆一下啊,诶刚才呢,我们提到了一个呢,叫做准备这个环节,在这个环节当中,它会给我们的这个order的这样的一个属性呢,赋值为。
13:09
零。对,这个呢,就是我们说的这个prepare这个时候做的,然后呢,这个initialization这个环节做什么呢?诶就是你把这个类呢,不是加到内存中了吗?然后我们就会把你的这个显示的赋值和静态代码块的这个赋值呢,在initialization的这个环节当中给你做了。哎,它这个做这个事儿的话呢,它是以一个方法的方式呢,来自动的去做的,哎这个方法的话呢,就是我们说的叫CL这个方法这个类的话呢,我们先做一个编译是吧。因为你要不编译就生成不了自检码文件了,哎,有了自解码文件以后呢,我们针对这个类呢,咱们去查看一下它的这个。呃,信息啊,然后在这个方法这块,哎,咱们以前也说过了,这个伊need呢,实际上是代表的一个构造器嘛。也不完全是构造期吧。对吧?哎,包括呢,我们当前呢,你要有这个属性,这个属性的显示复值的话呢,是不是也会在这里是吧?包括代码块中的复制也会在这里啊,但是呢,它为代表的你可以理解成是一个构造器啊,里面包含的这个信息呢,比较丰富一些,然后呢,下边你会发现呢,还会有一个叫c in,这个什么时候有呢?就是你当前这个类里边有静态的属性的时候才会有。
14:20
啊,有静态属性一定会有吗。哎,你比如说这个位置,我这样写的是吧。这时候会有吗?你看我们这时候呢,我们再重新的,我再编译一下是吧。变异了,变异完以后,你看我这刷新一下是不是没有了。因为你根本没有对这个属性呢,是不是显示赋值啊。啊,或者说你也没有在代码框中复制,只要呢,你有一个这样的操作,不管是代码块也好,还是显示复制也好,只要有一个。哎,我们再重新编一下。我这块呢,就会生成这样的一个。方法是吧,这块比如我们再增加一个吧,这给我来一个一是吧,哎,我再重新的再编一下啊。行,这边我们再刷新一下就可以了,行,那么这个CR的这个方法里边这个code的呢,诶他做的事儿就是把我们当前这个属性的一个显示赋值,不有个常量一嘛,然后给我们当前这个叫诶order de呢做了一个赋值一了,然后呢,我们在静态代码块里边,这不又来一个二嘛,然后再给我们当前这样一个属性呢,再去附上值。
15:19
那么这个方法在我们这个初始化这个环节呢,它就会执行。啊,就帮我们把这个方法一执行,那这个属性的值呢就有了,哎,当这个类呢,执行完这个初始化以后呢,它整个就结束了,它结束以后这个属性值是多少已经完全确定下来了。啊,就是这样一个场景啊。好,这是我们回过来这个呢,就是整个我们这个类的加载的这样一个过程,大家呢,了解一下就可以了。啊,不用去深究啊。好类的加载过程呢,我们说完之后呢,再接着说下边一个事儿。啊,这个也是一个了解的,我们讲呢叫类的加载器。A,加压器呢,我们在上面呢提到过,它是在这儿提到的。哎,这个类的加载器啊,我们只是出现在了第一个环节当中,也就是类的一个装载的环节。
16:07
哎,装载完以后的话呢,我们就会生成大的class的一个呃实力了啊呃,在这个环节中出现的这个类的加载器,这个环节和这个环节根本用不上它。哎,这个大家首先要注意好,那么首先一个作用呢,就是A的加载器是用来干什么的。哎,是不是负责我们这个类的一个加载呀。哎,并啊,生成啊,或叫对应于一个。诶,我们叫大的class的一个实例哈。诶,虽然说这块我们叫做类的加载器,其实呢,它也不光能够来加载类了啊,哎,包括我们上面提到这个接口啊,枚举啊,注解呀,也都是由这个类的加载器负责加载的,但是你总不至于起这个名。老是变嘛,所以我们总得有个名,所以呢,就统一的泛泛的称为叫类的加载器了啊。好,那这块我们听到这类的加驶器了,然后呢,我在这个里边呢,你看就写了几个类的加载器啊,然后呢,整个来讲说类的加加载器分成几种啊,这块我们看下这个课件啊,下边我们就来看一看这个类的加载器,它的主要的这个场景呢,就是负责把这个磁激码文件呢,诶加载到咱们这个内存里边。
17:13
哎,后边呢,还有其他的一些结构啊行,具体来说这个类的加载器啊,负责我们这个类的一个加载了,就不多说了啊,然后呢,看这个图,这个图里边呢,就呈现出来我们到底有几种类的加载器。啊,这儿呢,你会发现它有一个这样的一个层次的关系啊,似乎的话呢,是一种继承关系。但是你注意,其实不是集成关系。啊,这呢只是说是一个层次关系啊,哎,那么这个层次里边呢,你看比较顶层,这个呢,叫做翻译过来叫启动器。或者也称为它叫引导类加载器啊,然后下边这个呢,叫扩展类加载器叫extension。然后最下边这个呢,叫application啊,其实也可以称为呢,叫系统类加载器。啊,System class说的都是它啊,然后在下边的话呢,诶这是系统提供的啊,除了系统提供的之外呢,咱们作为开发者,我们还可以呢,自己去定义啊类的加载器,所以呢,就是这两个图。
18:10
那么通过这个图呢,我们想说明一下呢,这算式有几种呢?可能我们会认为说有三种,或者说呢有四种。是吧,诶但是呢,我们一般的哈,默认的时候呢,怎么去分类呢?诶我们是这样分的,下面这个呢,是自己一种,下面这几个呢是一种。啊,那这个分类的角度是什么呢?这里边这个不,我们也称为叫引导加,它不是用Java代码的。诶,它是用这个C和C加加这个代码来写的,而我们下边这个呢,他们都会有一个共同的负类,诶,那就叫做class loader。那ug呢,就是我们这儿呢,就是Java代码写的了。所以这块呢,我们就是以这个角度来进行了一个划分,说呢分为两种啊,第一种的话呢,我们就刚才写了啊叫boot。
19:01
Strip是吧,哎,这个class。哎,我们把它称为呢,叫做引导类加载器。诶或者呢,你看这块也写了个叫启动雷加在一起都可以啊。啊启动引导,那其实呢是算一个意思啊,这呢是它是一个了,然后下边呢,就是相当于是叫继承于啊叫class loader。啊类的加载器。OK啊,然后这块呢,具体来看的话呢,我们这块提到了第一个呢叫extension。啊,克拉斯。哎,然后这块呢,我们称为呢,叫做扩展类。哎,加载器是吧,然后呢,它下边这块呢,我们再提到一个叫做application,或者也称为呢,叫system啊。哎,你要是写system的话呢,这个我们翻译成叫做系统的压器是吧。
20:02
啊,其实呢,也可以称为它叫应用程序类加载器。啊,你要应用成列加去呢,这块我们就用这个词了,叫application,其实呢都可以啊,说的是一个意思。OK行,然后呢,再往下的话呢,除了系统给我们提供的之外呢,我们作为普通用户还可以呢,叫自定义啊。哎,加佳琪咱们这块呢,说的这个,呃,系统给我们提供呢,指的是JDK给我们提供好的这个呢,用户自定义啊,这个用户呢,一方面呢,是咱们。呃,大家呢,在开发的时候,你可以自己定义,还可以代表的就是一些第三方了哈,啊,你比如说像咱们这个tomcad。后边呢,咱们不是说在这个,呃,讲服务器端的话呢,我们把这个呢,作为一个服务器了集中起来,他盖里边呢,它也定义了一些类的加载器,那它属于哪一种啊。诶,它只能属于这个最后一种就是用户自定义了,就是这个用户的话,可能是我们也可能是一些非,诶Oracle官方的是吧,诶一些机构他们的电影类类的下载器都属于这个第三种啊注意。
21:10
好,这呢就我们这样的一个划分了,嗯,这块呢,需要呃多说两句哈,就是咱们现在写的这个类类加载器呢,是在JDK8的这个版本当中说的,从JDK9开始呢,这个类加载器呢,这个名啊,包括这个体系啊,实际上呢就变了。这话呢,一两句话呢,咱们说不清楚,而且本身这块呢,就是大家的一个了解性的内容,所以这块呢,诶我们就以GDK8为例来进行说明了哈,那杨IG呢,就这块儿呢,我其实需要做一个切换哈。哎,切换的话呢,我们找到这个,哎。这个Mo是吧,找到Mo这块呢,我需要呢,把它改成是这个JD8了。我就都换成八了。然后这个时期呢,我也提前呢,给大家先换一下了就啊。哎,就这么着了。啊,我就应用一下啊,因为呢,接下来我们要写这个代码测试的话呢,你会发现这个七跟18,呃八跟17呢,呃,打印出来的这个类的加压器呢,会有区别。
22:06
啊,这个区别的话呢,大家可以关注一下这个GM那个课程里边讲这个事儿了啊,咱们这儿呢,就不说这么细了,重点呢不是这儿啊好,那么首先的话呢,这里边提到了这样的几个类的加载器,下边一个问题就说,哎,为什么分这么多种呢?这么多种呢是吧,这有什么区别吗?哎,这呢,我们说啊,就是不同的类的加载器,它负责加载的类啊是不一样的。说你负责这一波,我负责这一波,他负责这一波是吧?诶大家的这个加载的类不一样啊,那时候我们就涉及到那启动力压器,你负责加载谁呀。来我们看一下啊。诶,首先我们刚才也提到了,说启动类加载器呢,它是使用C和C加这种代码来编写的了。没问题啊,那这种代码编写的这个类的加载器,如果我们试图去获取的时候呢,它返回的是个no。一会儿咱们演示啊,然后呢,它加载的。哎,这是游戏哈,说负责加载Java的核心库。
23:01
啊,这就是我们所说的叫核心库来回过来啊,首先呢,针于它的这样,针对它的这个说明,哎,我们说呢,其中的第一个点是吧,它呢是使用哎C或者是C加加。哎,这个呢,语言编写的。诶,然后呢,不能通过咱们的Java代码啊,获取其实例啊。这是我们说的第一个点。好,然后第二点它呢是负责加载,诶把它粘过来。诶,这样的一个位置,下边相关的一些核心的API,那么这呢,大家可能看着有点懵哈,你这想看GRE下边有个lib下有个RT点,这这个RT点,这其实就我们Java的核心的一撇都在这儿呢。啊,你看啊,诶我们看一下这里边的这个libraries点开,诶这个1.8也好,实际也好,这都行啊,比如1.8为例往下找,这不就有好多的这吗。咱们就去找这个RT点这。
24:02
就在这儿吗?这个RT呢,其实就是runtime的意思。哎,你把它再点开,哎,然后你这个Java呢,比如你一点开是不是就感觉很眼熟了。Long包啊,Net包啊是吧,Circle包啊,还有我们这个L包啊,U包啊,这是不是都很熟。啊,你比如浪包呢,我们一打开,你看是不是就我们常见的那些是包装类吧,这都。普类型的大的class object是不是都能找到在这儿啊,诶这呢,不就是咱们用的这个核心的一篇嘛,诶它呢其实都放在我们这个RT点这下了,第二啊,就是我们这个布class,他负责加载我们的核心的一啊。OK,这就是他的一个责任了,然后再往下的话呢,这不叫extension了,诶他呢。要扩展了加压器。啊,这个呢,具体的结构呢,是在这儿的啊,这个咱们一会儿呢,也可以稍微再看一下是吧,首先呢,它是集中于classo的,已经说过了啊,然后呢,它负责加载。
25:00
从这个位置啊,所指定的目录中加载库,或者是从这个位置啊加载的相关的库,诶大家呢,如果你看你相应的JDK的路径,它会有这样的一个路径,这个ET下呢,也有好多这个炸文件啊,这些文件里边的这个data的加载器呢,就是我们用的exce卡。啊,回过来,真的这个大家不用死记啊,就了解一下就行。他呢是负责。加载。诶往这一搁就行,这个大家做一个了解啊,不用深究,哎,我都懒得去这块去找了,大家你要愿意看,你就去你那个JDK里边,你找一下这路径里边有好多Java文件啊。把这个过了,然后下边这个呢,我们称为它叫系统类加压器,或者叫应用程序类加压器,那我们自己写的Java的一些类,比如像这个类啊,这个类啊,这个类啊,那么我们自定义类啊,默认呢,就是使用的这个类的压器进行加载的。啊,我们自定义的。啊类啊,默认。
26:00
使用的。啊类的加载器啊,我们知道这个事儿呢,就可以了。那用户自定义呢,用户自定你可以呢,呃,你想让它指定的去加载哪些类也是可以的。啊,咱们先说上面这个事儿吧,是吧,哎,上面这块呢,我们就提到了几种不同的类的加载器了,啊这呢提到了自定义类了啊,提到了核心的API了,好,那下面我们做一个简单的测试。诶,过来。整个这块内容大家注意啊,是一个了解的啊。Class的一个测试啊,写一个单元测试方法啊。哎,这么着啊。注意啊,我在这块写一下,大家呢,去运行这个代码的时候呢,我们是在JDK8种执行如下的这个代码,你要放在JD时期里边呢,就会有区别啊。好,那么怎么办呢,我呢先主动的啊去获取。什么呀,那叫系统类加载器。那就是获取一下这个是吧,啊这个怎么获取呢?通过这个大的class loader呢,它有一个方法叫get system class loader。
27:04
哎,我们al加个回车,这呢就得到了一个class。诶,这个呢,其实就是一个叫系统类加载器了。来我们这儿呢,去打印一下啊,这个class都是一。走起。哎,运行一下,哎,这时候呢,你看他打印出来的叫APP。这个呢,咱们是两名是通用的啊,你叫系统类加载器也行,叫诶应用程序类加载器也可以啊,这个呢,拿到的就是它,诶我们把这呢打印一下是吧。好,然后呢,呃,这里边儿呢,大家你会发现呢,他们有一个似乎是一个继承的关系是吧。其实不是。啊,但是咱们等一下去说这个事儿啊,哎,我们可以理解成呢,就是它的上一层是它。啊,那怎么拿到它的上一层呢?我们通过这个斯洛伊呢,叫get,一个叫parent。诶这样的话呢,我们就得到它上层的一个class斯点了这个我们比如说叫二,它的上层就是扩展类加载器。
28:02
哎,这个我打一下这个克拉的二,哎,走起。好,那么这个结果的话呢,哎,我们把它粘出来,你看一下这个位置呢,叫EST就是extension。啊,那就是扩展类的意思啊,哎,扩展类加载器。哎,没问题啊好,那么这呢是获取。扩展类。诶加载器啊啊,然后呢,扩展类加载器呢,你看它的上层呢,是这个叫启动类或者叫引导类加载器了,那我们拿着这个CLASS2,咱们再去点get一个这个parent是吧。哎,再往上去找这个呢,叫class6.3了。哎,这个呢,如果要获取呢,那就是引导类了。哎,就他来我们去做一个运行。好,诶此时的话呢,诶,我们发现呢,这块我们得到的是一个nor。说白了就是我们没有获取成功,不是因为呢,它没有上层的是有这块呢,因为咱们这个启动类加载器呢,不是用Java代码写的了,所以呢,你也不会获取到一个类似于Java这样的一个结构的一个,哎。
29:09
显示了。啊,所以这块呢,我们写一下啊叫诶获取引导类加载器呢,注意是失败的是吧。哎,失败失败就意思,我们获取不到的意思啊,拿不到了啊。那这个呢,你可以想象成,比如说呢,嗯,这个咱们作为普通老百姓是吧,你出去呢,吃一些饭店呢,做的这些美食呢,这都没问题的啊,那你像这个英国呢,现在还有这种皇室是吧,你可以想象成这个皇室里边呢,有一些这个御厨。啊,人家呢作用呢是就只给这个皇室这个成员呢,去做这些饭菜的,可能做的也挺好,人家呢是不负责呢,对外呢,给普通的一个民众呢做的,当你试图了,你说我就想让他给我,哎做一道菜啊,做一桌饭获取不到。啊,就好比是呢,我们这个御厨呢,就相当于是叫引造了加载器,它呢只负责Java核心API的一个加载,你想拿到它,接着让他主动的去加载某一个自定义的类。
30:05
好使,根本都拿不到。诶可以这样来来去理解啊,行这呢,我们就是先有这样的几个结构了,接下来咱们看一看啊,是不是像刚才说到的,比如说我们自定义的类。啊,比如就像这个user色类了是吧,User色类的话呢,咱们就可以这样了,诶咱们使用其中一种方式吧,比如直接呢,就是优色点class啊这呢,我们就得到了一个大的class,这不一个实例吗。哎,前面我们讲过这个事了啊,好,拿这个CLASS1呢,这不就是你这个对应的运类吗?我呢,就是get你的一个class load。我想看看呢,你这个类呢,是谁加载的你。啊,叫get class啊。好,这块我们打印一下啊,这个拉。是吧,这块我们做一个执行。好,出来这个结果呢,你会发现呢,它是APP class是不是就我们这个吗。
31:02
啊,那就说明了,咱们用户自定义的类,呃,使用的是系统类加载器加载的。哎,自定义的这个类啊,使用的是。那系统类加载器啊。加载的。啊,这呢是我们说的这个事儿,好,那咱们再换一个哈,再换一个是不是就润了。String的话就属于我们的核心的API了,那咱们再换一种方式加载,都熟悉熟悉啊,这块写个二,通过这个class.for name主动的我们去加载Java点包下的string。啊,这是一种方式,这是一种方式啊,体会一下不同的方式。泡一下。然后呢,我们下载过来以后呢,拿着这个诶CLASS2,我们去get这个class load。诶这呢,我们也能得到一个class,我们把这个呢打印一下。就这样走起。嗯,出来了啊,这时候你发现呢,打印的是个no,那说明呢,你就没有获取到,那没有获取到的可能性,只能说呢,你是用的引导类加载器。
32:07
所以我们通过这样的一种方式呢,去做了这样的一个证明啊,这个大家注意一下。这我们写一下啊说呢,对于Java的这个叫A核心。啊,API使用呢,叫引导类。哎,加载器加载。OK啊,这个呢,大家注意一下这个事儿就可以了,行,整个这块呢,大家做一个了解就行啊呃,然后呢,回过来以后呢,这呢,我们不就提到这样几个类的加载器,这两个它呢是继承于class loader的是吧?它是在哪儿呢?这在我们刚才这个演示当中啊,你也能看到了,它是在这样的一个类里边定义的。一个它啊,一个是我们这个阴道类加压器,或者你在这个位置啊,我呢来一个叫CTRLH。哎呢,是不是就过来看我们这个class它的一个体系结构了啊这个呢,类加载器,它下边呢,有一个子类叫做secure class是吧,它呢点开以后。
33:01
这里边有个叫ul,再点开,然后这里边有一个呢,叫做extension。啊E,然后还有一个呢,叫APP的这两个呢,它就是引导加载器。他呢?哎,叫。哎,系统类加载器,或者叫应用程序类加载器是吧。没问题吧?好,那么从这个图上来看的话呢,大家你会发现呢,这个类和这个类这算什么关系啊。并列关系是吧。哎,他俩呢,是不是都共同的继承于这个类啊。这个类的复利是它它的复类呢是它它的复类呢是object,整个呢,这是一个层次关系。哎,从这个咱们说一个树的结构上来讲呢,这俩是不是算兄弟啊。对的啊,这是从基准关系上来讲,但是呢,你会发现呢,我这里边诶,或者说我们通常大家你看到这个类的加载器的时候,通常呢,都写成这样的一个方式的,似乎呢,给我们引导的是说呢,好像说这个系统类加载器的副类是它一样是吧。
34:01
其实不是啊。啊,其实不是,但是的话呢,我们平时叫的话呢,还真这样叫。什么意思啊?我们一般都说系统类加载器的负类加载器是谁呢?是扩展了一个奇。扩展类加载器的负类加载器是谁呢?是启动类加载器,注意你看这块我都用了一个叫负类加载器了。啊,就是这样说,但是你要注意,他们是没有继承关系的。他们俩是一种什么关系呢?我简单的给你描述一下啊,其实是这样的一种关系。你看这我也写了啊,说是不是存在竞争关系no是吧。没有基准关系啊,它其实是这样一个特点啊,比如我这块呢,就声明了一个叫。哎,我叫一个哎,Class loader。哎,注意这个克拉的其实。嗯,你也可以理解成就是咱们这个刚才说的这个类的这个class loader啊,你也可以理解成是他,然后在这里边呢,我这样子,我再声明一个class loader。
35:02
我叫做什么呀?我就叫parent了。教堂,然后这块呢,我们来一个构造器啊,比如public和last load这个位置呢,我就声明这样的一个行参嘛。我叫Z4点,哎,Parent等于这个parent这个大家应该都很清楚啊。那然后呢,怎么办呢,我下边这块呢,就在具体我们这个测试代码当中,哎,我就拗一个它是吧。哎,我叫做a load1吧。哎,我叫LOADER1啊,然后你有一个这个叫class loader。诶这块你完的话呢,这块是不是需要传一个这个参数是吧,这个参数的话呢,比如我们提前的就造好。哎,我这块造一个假设,我这个呢写成叫零,然后把这个零的话呢,我就传到这儿了。然后这个话呢,是不是就。传给他了,他呢,就传给他了,就传给这个了。相当于呢,我们这个LOAD0是不是作为我们这个LOAD1的一个属性出现的。
36:03
哎,那么这样一种结构当中说呢,我们就把。哎,谁呀?哎,这个零啊叫做。哎,一的。哎,负雷加压器。啊,就是我们现在说的这个呢,就是他们的一种本质上的一种关系哈,从这个继承关系上来讲呢,这个哥们儿跟这个哥们儿呢,他俩其实是并列关系的,是兄弟啊,我们呢,其实是把这个extension class load呢,它的具体一个对象呢,诶作为一个诶参数啊,付给我们这里边一个属性了。啊,然后呢,彼此之间就构成了一个我们这样的一个层次关系了,然后呢,我们就说呢,是一种呃,这样的一种关系了。大家可能会有疑惑。凭啥呀?或者说图什么呀,为什么呀,是吧,哎这呢一说的话就多了,因为这里边儿涉及到了一个诶类加载时候的一种机制,这种机制呢,称为呢叫双亲委派机制。
37:02
说完之后呢,是不是都没有兴趣去了解了?是吧,这名字呢,就起的就很吓人是吧。啊,其实呢,也不是特别复杂啊,我简单的说一下,为什么习惯性的我们把它们写成这样一个关系,让人误认为是一种继承关系呢?啊,因为呢,就是想这样先放,放完以后呢,假设我们现在来了一个类了,啊,这个类呢,现在要加载了。它这个加载呢,是有一个机制的,这个机制呢,就是先拿过来之后呢,我们先走到这儿,假设现在都还没有这个事儿呢,是吧。我先走到这儿啊,先试图呢,让这个系统类加载器呢去加载,但是这块呢,这个类注意你刚来之后呢,不能够让它去加载啊,哎,我们就得往上跑。给了这个扩展类加载器,扩展类加载器呢,接着往上抛,抛给这个叫引导类加载器,引导类加载器呢,看一看说呢,我是不是合加载。这就相当于在判断呢,是不是我们刚才说的那个相应的路径了,是吧,如果在那个路径下呢,我就在不在那个路径下,我是不是就不加载啊。
38:00
哎,首先如果是这个路径下载好,我负责加载,一旦呢,我们启动类加载器加载完以后。下边这个呢,就不再加载了,保证呢就只有这一份儿。好,那如果说呢,我们这块呢,一路往上走,走到这儿的时候呢,呃,启动类加载器一看说候呢,诶我不适合加载,那它就不加载了,它不加载的话呢,它就甩给这个扩展类加载器了。扩展类加载器呢,看一看说我适合加载吗?一看我也不适合加载,我也不加载,然后呢,就走到这儿了,这儿呢是我们说的默认加载器了,到这儿以后呢,诶新的加载器就负责加载了。所以它有一个整个加载的这样一个顺序,把这种顺序关系呢,我们就称为呢,叫双亲委派机制了。哎,大家可能会想说,为什么要这样子是吧?啊,你比如说咱们现在呢,来了一个叫Java点。浪包下的。String是吧?那很显然呢,这个加载顺序呢,就是这个呢,是不是先走到这儿,这个送上去,送上去在这儿呢,是不是加载了。这样呢,我们就加载成功了,然后下边也不负责加载。
39:02
啊,就是说这也没啥呀,你注意哈,我们也完全可以自己呢,在Mo下我定一个包就叫浪包。我在下边儿呢,我自己定一个类,叫做使命的一个类。然后里边你一顿写代码。啊,这时候你注意哈,你写的代码的话呢,你里边用到这个string,假设你在其他这个代码里边用string了,也是浪下的string,它会误认为呢,用的就是你自定义这个了。你想说去替换核心API的这个,注意你这样写替换不了,为啥呢?因为我有双亲委派机制。啊,当你自己这个呢,你试图加载的时候呢,往上走走走走走走到这儿了,你看你这个肋是不是浪了。一开始唠了,然后呢,这个boos说,诶这应该我来加载,他加载的时候呢,他就去,诶其实还去那个核心的那个API那个包里边去加载了,加载的时候呢,发现跟你这个就不一样。他就不会去加载你这个了。这样呢,就使得整个我们这个,呃,数据呢是安全的。要不你会出现一个恶意的替换吗?
40:00
你想是吧?我们在一个项目当中是不是老用啊。你自己定了个叫浪包,然后也叫磁轮,轻轻易易的很轻松的就把这里边这个磁轮给替化了,那哪能行啊,我们在加载的时候呢,根本就不考虑你是因为呢,诶你加载时候呢,不会归他管,都走到这儿的时候呢,他还是去那个,一看你是浪包嘛,我就还是去那个RT点这里边去加载,就根本就没有管你这样呢,就很好的保护了我们的程序了。啊,可能似懂非懂。是吧,嗯,这个呢,就只能是先说到这儿了啊,OK啊,也就是说呢,你看啊,我们假设哈,咱们在当前这src下呢,你看我这块试图去一个叫做。看有没错吗?然后呢,这里边儿呢,你说我就自己呢,非得定一个类,这个类呢就叫做string是吧。然后这里边儿呢,你可能就会定义很多的方法,你甚至说呢,你把这个string里边一些方法拿过来,你自己呢,偷偷的改一改,恶意的做一些注入的行为啊,注意你这个行为呢,其实是不好使的。
41:00
哪怕你说这边我们简单点写个main方法是吧,写个hello,那这个呢,你想试图去运行,注意这个事儿呢,成不了。搞错了是吧。嗯,这个是不行的,为啥呢?因为呢,我们这个类呢,在加载的时候呢,你是浪包下的,然后呢,引导类加载器来负责的,他根本呢发现呢,这个包我们去。诶自己呢,在阿吉尔大包里边去找的时候呢,跟你这个不一样。所以根本就不会去加载这个类啊,因为这个类的话,你像我要别的位置要用了。还挺麻烦的。诶,我看看这里边儿有有用的这个场景person里边的。这个string是吧,这时我点一下啊,这样点到这儿来的是吧,就是你要是出现这种替换行为了,那不就会被我们这些类呢,都会受影响。哎,所以这不靠谱啊。这个我就注释一下了啊。好,所以呢,因为有刚才这个双性委外机制呢,那咱们说呢,层层往上嘛,所以习惯性的话呢,就写成这样的关系了,但是注意这不是基准关系啊。啊,就有点像这个,咱们说古代这个选妃一样是吧,这个从地方那选过来这个美女,是不是先到这个地方这块,地方这块呢,你你不能拦着是吧,你看着特别漂亮,那也不行,往上送往上送,送到皇帝这块呢,皇帝一看挑完了以后呢,剩下的往后是吧。
42:16
诶得得这样一个顺序例子呢,也不太好是吧。现在我们是男女平等的哈,嗯,好,就是这样的一个过程啊,稍微了解一下,然后的话呢,简单再提一下,我们后边不还有叫用户自定义类加载器吗。那这块就提到说,诶干嘛还用户自定义呢。这不用的好好的吗。是吧,干嘛还自定义呢?诶,这个我们AA在这儿是吧,诶用户自定义类加载器。诶这块呢,其实就会提到一个点,我就简单说一下啊。这个类的加载器,你比如我们说这叫系统类加载器,它呢,如果去加载一个,比如说咱们说的这个user啊。User,诶咱们前面提到了,说这个运行时类只会加载一份。我刚才这块提的时候呢,其实我说这个事儿呢,不是特别准确是吧。
43:04
说这个运行实内呢,在整个内存中执行期间只会加载器,我说这块呃,只会加载一次啊,我说这块呢,不是特别准确,准确的来讲呢,应该是诶同一个类的加载器只能加载一份。你要是不同的类的加载器呢。就可以下载多份了。哎,比如我这儿呢,是一个class load1,哎,我们这呢是一个user类,我呢可以加点一份。如果要是这块一个新的一个class load的话呢,我可以呢,再加载一份。诶可以这样子的,但是咱们一般呢,都是用的系统的加载器,而且呢,这个系统的加载器的话呢,你看咱们刚才测试的时候,这块拿到的是不是就这个是吧?然这块我们在使用这个优class时候,你看拿的是不是跟这一样啊。也就是说呢,咱们这个性能加载器呢,哎,咱们其实通常也就用这一个就行了,那就既然你平时就只有一个,这就意味着我要是想加载这U4呢,是不是也只能加载一份了。那如果呢?在一个程序运行过程当中,我们想加载多个。
44:04
你想想你是不是只能是自己去定义类的加载器了。诶,那这呢,就是我们呃,自定义类的加载器的一个原因。就是说呢,我们在这个程序当中,如果你想加载多个啊,比如说这个user吧,那你就得是使用自定义类叠加器,那下个问题就是说我们为什么要加载多个呢。呃,因为呢,这个类呢,可能会有不同的版本。啊,咱们在平时开发当中,比如一个项目里边,我们可能用诶某一个炸包了,这个呢,你在这个模块里边用的是这个炸包,结果这个项目更这个炸包更新了。更新以后呢。这个可能还有一些冲突,会有一些问题,那怎么办呢?我就希望呢,把这个炸包跟这个旧的炸包都加载过来,都加载过来同样的类,那你咋能同时都加载呢?是不是我们就自定义类的加载器了,哎,我们这块呢,把你也加载了,你在这里边用,哎我这整个类的加载器呢,诶我也加载了,你在上面这块用。哎,这呢,就实现了一个,哎,我们叫应用的一个隔离嘛。
45:01
在同一个应用当中,我们针对某一个类呢,可以加载多份嘛。哎,这叫实现应用隔离是吧。了解一下啊,这个以后我们讲后边高级内容都会说啊,实现一个叫应用的这个,诶隔离就是同一个应用里边,我们针对某一个类可以加载多份嘛。在这写下啊。这个诶同一个。啊类是吧,在一个啊应用程序中。哎,可以加载。多份。啊,这个主要原因呢,就是因为我们这个,呃,每一个类的加载器只能加载一个类了,那你多个加载器就可以加载多个类啊。呃,这是一个点啊,另外还可以呢,实现一个什么点呢,实现我们叫数据的一个加密啊。你比如说呢,我们啊,大家你看到了这呢,都生成的C解码文件了,在我们这个idea当中,轻轻松松的这块呢,你点一下是不是就反编译了。啊,那如果说呢,我们这个数据呢,你你你给给出去了,给出去之后呢,然后呢,他拿着自写码文件呢,直接一反编译呢,就知道你这代码怎么写的了,然我们在生成这个自解码文件的时候呢,我就加密了,然后呢,我们在加载使用的时候呢,放到内存里边我再解密,这时候你就使用你自定的A加载器对它进行解密就可以了。
46:18
哎,这个数据的话呢,就可以,诶在自检码文件这个层面呢,就可以呢,去保密了是吧。啊,这个呢,就是我们说的这样一个特点啊,行这就过了。整个我说的这个内容大家做一个了解啊呃,然后最后这块呢,有一个需要掌握的点,说使用类的加载器呢,获取流啊,读取配置文件的一个信息,这个呢,咱们稍微的写一下。啊,刚才说的这个事儿呢,大家了解一下啊,哎,下边要讲的这个事儿呢,大家稍微的注意一下。什么呀,这有个需求。说那叫诶通过pay,诶通过这个class啊。哎,然后呢,我们去,诶加载指定的啊,这个配置文件咱们在前面呢讲过读配置文件的事儿,想想在哪讲的。
47:07
对,是不是我们讲这个properties的时候啊。还有印象吗?在讲我们这个集合框架的时候呢,我们说呢,是不是讲过这个叫properties是吧。Proper proper。T是吧,哎,他呢就来处理属性文件的嘛。哎,当然我们讲的时候呢,还稍微提了一下,我说大家呢,先不用可以掌握,因为我们还用讲IO流,咱们现在已经讲过IO流了。诶,咱们快速的我把这个呢,我写一下啊,咱把这个事呢,讲完以后呢,咱就结束了啊好,然后呢,咱们当时呢,去读这个配置文件的时候呢,当时还稍微提过,哎,你要是使用单元测试方法的话呢,默认读的是不是当前这个Mo下呀。好这块呢,我们去新建一个哈,哎,具体的一个file了,比如说呢,我们就称为呢,叫做infer第2PROPER。
48:01
哎,Teeth是不是这样写的,在这里边我们写个name,哎,比如呢叫哎Tom啊,然后呢叫。诶,Password吧。哎,这个呢,我们写成ABC123。行,我这样稍微再这样盯一下啊。好,我把这个配置文件呢,写到咱们当前这个叫mole下边了,然后呢,回过来,哎,快速的我这块写一下啊,首先呢,我们叫a properties。啊,然后呢,叫props new一个叫properties。哎,这么着啊,然后接下来呢,我们通过这个a prop点,我们可以呢去load load呢需要个流,那流没有没有提前造一个这个,比如叫file。哎,Input stream啊,这不就有个is了啊,你一个file input stream这两去你一个file。诶,然后这块用这个file的时候呢,咱不是说了你相对路径呢,就是当前model下嘛,诶我就把这个呢,CTRLC一下,我们就搁到这儿了,诶有异常我们都抛一下。哎,你一,诶这写错了是吧。这个吧。
49:00
好,这块呢,Alt加个回车,哎,把异常我们就抛一下行,然后咱们把这个流呢,是不是就放到我们这个漏里边了啊,这块有异常呢,我们也给它抛一下啊。这样的话呢,我们就通过呢,诶当前我们这个pro呢,去诶读取我们这个当中的这个文件中的这个数据了,那接下来的话呢,我们不就是通过这个pro get叫property啊,因为呢,它呢处理的键和值都是string类型的,这个我们键呢叫name。哎,这呢,就返回它对应的这个Y6了,假设我就要name了啊,然后pro.get property。啊,这个对应的我们叫password。哎,这么着是吧,然后返回一个就叫PWD了,咱们就直接呢,可以打印一下了。行,这个是咱们前面讲过的这个代码啊,我就快速的写了一下。你看这个这个Tom abc123我们就能获取到了啊,这个如果你要写的这个不靠谱的话啊,他不会报异常,只能说呢,我们去找这个K的时候呢,没找到啊,返回来就是一个not了啊。
50:02
诶,这个细节呢,稍微大家注意一下啊好,这呢是咱们前面讲到的,以后呢,咱们在呃,写这个程序的过程当中啊,会实现这个叫数据和代码的一个分离,数据呢,我们就放到具体一个配置文件里了。好,现在我们说呢,使用这个class呢,也可以做这样一个事儿啊,但是这块有个小区别。来大家你看啊,我把它呢,CTRLC一下,原封不动的我粘过来。啊,我们说能做这能做这个事儿呢,主要呢,点是指的是用它呢,来替换咱们的这种方式获取这个流。就仍然呢,还是需要一个流的啊,只不过呢这块呢,我们把这个呢给它干掉了。哎,怎么能拿到这个流呢,咱们使用的这个叫a class loader。哎,Class,首先我们去获取一个叫system。相当于拿到一个系统的加驶器啊,它呢有一个呢叫get resource as stream。挺长的一个方法啊。拿到一个资源作为一个流是吧,所以作为一个流呢,拿到一个资源,这个资源是谁呢?可能我们想到说,诶,这不就是我们这个资源吗。
51:05
诶把他那拿过来,他呢,得到的就是一个叫input stream。那这呢,就是is了。哎,这个有异常,我们也给大家去抛一下,所以呢,我们说这种方式呢,其实主要呢,就是替换一下我们这里边儿这个操作的啊。哎,这个呢,就换成他了。哎,那这个写完之后呢,靠谱不来跑一下啊,走起。好,大家看这个呢,是不是就报错了,说明我们现在这块呢,写的是有问题的啊,这个第62行,哎,在这块呢,报了一个叫诶控制人的啊,诶这个呢,加载的时候呢,相当于我们这个流呢,就是没有正确的获取到啊,那什么原因造成的呢?诶不是因为我们这个文件名写错了,咱们直接粘过来的嘛,主要原因呢,是因为我们此时啊。诶,我们说呢,通过叫类的加载器读取的文件的默认的路径为。
52:01
哎,我们说呢,当前叫module下的。S2C小。哎,说白了就是这个路径呢,是有问题的啊,咱们这种方式的话呢,咱们在这写一下啊。哎,读取的文件的默认路径为。当前的这个猫。啊,那上面这个话呢,它是在SC下,你显然呢不在嘛,所以呢就出错了啊,那比如我们这块新建一个啊在src下,我右键呢,去创建一个具体的一个。啊,比如说呢,哎,我们写成叫in for一点,诶proper。其次是吧,然后呢,这个信息的话呢,咱们比如说跟它类似吧,哎,把刚才这里边儿的这个CTRLC咱们呢,粘过来,这个我就换成一个。托尼是吧?比如密码来一个哈。哎,这样写的啊好保存一下,然后呢,这个呢,信息呢是它,然后呢,回过来这块呢,我们接着呢再去读这个呢,注意就不是in for了啊,注意IN1了。
53:00
哎,就我们当前这个src下的这个哈,然后呢,再去这个load获取name,获取password,应该是他了,走起。哎,你看这时候那就没有问题了。诶,所以这个呢,就相当于是给了我们另外的一种方案哈,咱们可以呢,去读取这个配置文件的一个数据的。啊,一种方案是这个,一种方案呢是这个。啊,这块的话呢,两种方式大家需要去记一下啊,所以这块呢,我们如何去读呢?诶这个代码呢,CTRLC就相当对应过来,我们是这个事儿,诶大家呢,需要呢会去写这个操作就可以了啊。行,那我们讲了这么多关于类的加载过程,类的加载器,其实呢,最后落地呢,需要写的代码呢,是它上面呢讲的这个事儿。啊,加载器也好,加载过程也好,大家做一个了解就行。那整个呢,咱们今天呢,就讲到这儿啊。
我来说两句