00:00
行,那咱们关于动态链接呢,咱们就先告一段落,那或者呢,咱们说叫指向运行时常量池的方法的引用呢,咱就告一段落了啊,就是用这个更长的这个来说明咱们现在要讲的这个内容呢,我觉得反而是更加的清楚一些的啊行,那这个呢,咱们就先告一段落,然后再讲下边剩下的两个,一个叫方法返回地址,一个呢叫做一些附加信息,之前呢,咱们再讲一个比较重要的内容,叫做方法的调用啊,这儿呢,是咱们这一章剩下的这块内容里边的一个重头戏,反而呢,是咱们剩下的这个方法访问地址和一些附加信息呢,倒比较简单啊,比较简单我们就能够讲清楚了,那这个方法的调用呢,作为Java程序员呢,其实你天天都在写方法的调用,那你是不是能够透彻的理解其中的一些原理和Java虚拟机呢,执行的一些这个过程,那不一定那么讲介讲述这些内容呢,诶希望大家能够有对平天天在用的这个方法呢,有一个更深的一个理解哈,讲。
01:00
我们来看一下这里边呢有哪些具体的信息,嗯,说呢,在Java虚拟机当中,将符号引用转化成调用方法的直接引用,与方法的绑定机制呢,是密切相关的啊,这个提到了我们说叫符号引用转化为直接引用,这个咱们在讲动态链接的时候呢,这不是也反复的在说这个问题啊,呃,这是咱们写的这个程序,咱们通过这个JP呢去解析的时候,在咱们的方法内。咱们找个方法,呃这啊这构造器了,嗯,构造器也行,其实用哪个都行,在这里边呢,你会发现呢,咱们调用了其他的一些这个,呃,这个方法是吧?诶这呢是调用这个输出语句的是print stream里边的这个,呃,这个相应的这个print line这样一个方法了,呃,这个包括我们像这里边这景五是咱们调的啊,这个是最屌的print LA哈,然后下边这个方法B呢,这不是调了咱们这个方法A等等,像这呢,这都算是对应的叫符号引用,这都叫符号引用,然后呢,我们真正在这个执行的时候呢,都需要把对应的这个符号引用呢,对应到它相应的这个叫直接引用上啊,去我们常量池里边找到对应的直接引用的这个相应的一个位置啊,再从这样引,一直找到我们这个方法A,诶这样的一个情况啊,这呢就是提到了这个。
02:19
这个符号引用到直接引用的一个引用过程,这个转换过程,这个转换过程呢,跟这个方法的绑定机制呢是相关的,哎,咱们说那个Java语言呢,是一门面向对象的语言,那面向对象的语言呢,有一个特性叫做多态性,那么虚拟机它是怎么知道运行的时候呢,应该调用哪个方法呢?诶那咱们来看一下啊,这呢,我们提到了有两种链接方式,一种呢叫做静态链接,一种呢叫做动态链接。何为静态链接啊,静码就是我们说不变的这种是吧,叫静态的啊,说当一个磁解码文件被装载到虚拟机的时候,那如果被调用的目标方法在编译期间就可知,而且在运行期间保持不变,那这种情况呢,我们就把它称为叫静态链接。
03:06
再说一遍啊,就是这儿呢,我们主要的关注就是符号引用转化成直接引用,这是一定要转的了,关键的就是这个转化过程是在编译期间确定下来的,还是在运行期间确定下来的。那如果在编译期间就确定了符号引用到直接引用的这个确定的方法了,我们就称为叫静态连接,那如果编译期间确定不下来,在运行期间才可以确定下来的,我们就称为呢,叫做动态连接。这呢是咱们针对于这个方法来说的啊,叫静态和动态,那把这个概念呢,咱们再推广一下,诶大家看一下,我们又提到了这里边的对应的方法的这个绑定机制啊,称为叫早期绑定和晚期绑定,哎,这又对应了一组词啊,那这里的早期绑定其实就跟咱们的静态链接是对应的,晚期绑定呢,跟我们的动态链接是对应的啊什么叫绑定呢?它是一个字段,就是我们说的属性field方法或者是类,在符号引用的时候呢,被替换为直接引用的过程啊,它就发生一次,就是说一旦你确定了绑定的这个结构了,那它就不会再被修改,不管你是在编译期确定的还是运行期确定的,一旦确定了就不能再修改了。
04:22
啊,这个绑定的概念更大一些,针对的像字段方法类啊都算,那咱们目前呢,主要关注的还是方法啊,那我们看一下这个所谓的早期绑定,就是呢,目标的这个结构在编译期就确定了,运行期保持不变,哎这个呢,我们就是说它在编译的时候呢,比较早就能够确定下来,就叫早期绑定,那对应的就是编译期确定不下来,在运行期才能够确定下来了,叫做晚期绑定,哎其实就跟咱们刚才提到的这个动态链接跟这个短题绑定,它俩是对应起来的。对吧,哎,这个比较清楚啊,行,那说到这儿呢,咱们来举一个具体的例子来看一下啊,这个例子呢,相对来讲不复杂,哎,这是我这个为了能够说明咱们这个问题呢,给他拼出来的这样的一个例子,咱们看一下啊,这个咱们来说明一下,哎,叫早期。
05:16
绑定和哎晚期。绑定的一个例子。OK,看一下,那这呢,我定义了这样的几个结构哈,大家看一下,这呢是一个animal,一个类啊,有一个eat的方法,动物进食这呢有一个接口,这个是hunt hunt是捕猎啊,Hunt我就可捕猎的一个hunt方法,这是一个抽象方法接口嘛,然后呢,我们定义了两个动物,一个是狗,一个是猫,嗯,这呢我用的是都比较形象的这个类哈,就是容易大家直接呢就能够形象的去理解,然后狗跟猫呢,都是继承了animal,然后都实现了ho的接口,那就它同时呢,诶都重启了接口中的方法和我们it这个animal里边这个eat方法。
06:01
都重启过了,猫吃鱼,狗吃骨头,哎捕猎的话呢,就是狗拿耗子都管闲事,猫呢就是,哎捕捉耗子天经地义,哎不过现在猫呢都泡好的了是吧?行,那这呢是我们列举出来的这样的几个类哈,然后呢,下边呢,咱们在animal test这个测试类当中呢,行参我放的一个是animal这个负类,一个呢是咱们这个接口,哎内部呢,就各自调他们各自这个负类也好,接口里边这个方法,那我们说呀,这个animal.e的方法,它其实在此时就表现为。表现为是不是叫晚期绑定啊。对吧,诶它表现为就是晚期绑定,那对应的咱们这个接口呢,那就更是了,因为接口咱们说本身就不可以实例化嘛,那那你这块呢,要想能够调用how的方法成功,那一定是提供它实现类对象来调用这个方法了,那到底是哪个实现类呢?不确定啊,我也不知道你现在要调哪个这个这个呃,事前类的对象呢,是吧,所以这个就没法确定了啊不,不知道是狗狗抓耗子呢,还是猫抓耗子,这个就确定不了了,那这两个呢,就是我们所谓的叫晚期绑定,就在编译期间呢,咱们确定不下来。
07:17
哎,这样的情况啊,那这块呢,我们把它做一个呃,Re compile编译。啊,编译了,编译完以后呢,我们看一下咱们当前这个animal test啊这个结构,嗯,看一下它的这个这class lab,这个animal test,然后点开它method,我们看一下这两个方法,那这两个方法呢,打开以后,那么在这个位置能看叫invoke virtual。啊,然后在我们这个接口这块呢,叫interface,诶这两个呢,其实体现呢,就都是啊两个这个方法调用这块的指令哈,这两个指令呢,其实对应的都是算咱们晚期绑定或者叫动态链接,诶这块的两个指令。那这个咱们之前这个好像应该没说过啊,就是大家呢,你对于具体的这个指令如果呢不清楚,你想了解的话呢,其实你可以点击一下这呢,就直接能够链接到咱们Oracle的这个官网,对刚才看到的这个啊a load杠啊进行一个解释啊,参数呢是几个意思,这个呢,咱们咱们到后边专门讲自检码指令的时候呢,带着大家来讲啊,你要是首次关联的时候进不来,或者说进入这Oracle了,它报错了,你刷新一下啊,就链接上了,诶后续呢再用就没问题,那invoke virtual什么意思呢?这个也是直接点击呢,这都有介绍。
08:33
啊,不过大家你好像看到这个说明以后呢,呃,是不是有点懵啊,这个就感觉头大是吧?诶那你要是基本上了解这个观念,这个指令以后呢,你再看他这个描述呢,你会感觉很清楚,那如果说一开始完全对这个指令不清楚的话呢,那就算了,所以大家呢,你还是等着后边咱们这个发放后续的这个视频就可以啊,就是当大家呢,把这个内存和嗯垃圾回收片看完以后呢,这个后边的这个自己码指令跟类的加载这篇呢,篇章呢,基本上我也就都录好了,你就跟着看就行,哎,就是大家能够整个呢,关于GM呢,有一个全貌的认识,OK,诶就行啊。
09:14
好,这呢是咱们说的这两个啊,它俩呢表现为就叫做晚期绑定了,那晚期绑定在我们Java当中,除了晚期绑定啊,体现了这种多态的特性之外呢,它有没有早期绑定呢?当然有,当然有啊,那比如说呢,大家你看我们这个cat里边它的it方法,我在这个位置呢,我去调用一下叫做super.e方法,相当于我们在子类当中呢,调用了父类中的被重写的这个E的方法,对吧?诶这是一种情况啊,还比如呢。嗯,还比如说这个例子。我们还可以是不是写这个类的构造器,对吧,那我这写一只猫,哎,这一只猫呢,比如我们调一个super,它然后呢,我再写一只猫。写一只猫,创建一个猫的构造器,啊,这呢,我写一个,比如说in string吧,来一个name。
10:07
这呢,我就写一个这次调用当前本类的构造器。好可以了,那我们再做一个重新的,呃,Re compel啊,重新的一个编译。编译完以后呢,大家这时候我们想看的就不是咱们的animal cat这个字节码文件了,而是这个cat的,所以你把光标呢放在cat这,然后我们再来点一下这个接class lab,那这就我们这个猫的了啊,然后看这个方法这块,那这个就有两个了,对吧,因为我们有两个构造器,那第一个构造器呢,你打开我们此时呢,调用的是副类的这个构造器,这呢有一个叫ino special。啊VO special,然后下边的这个呢,呃,点开以后呢,也是叫VO special啊,一会儿呢,咱们会说专门关于这个叫虚方法调用的这个指令啊,像这两个呢,就是在我们这个编译器你就能确定,这这呢指的就是cat这个空参构造器,Super空呢指的就是咱们啊这个animal里边默认提供的这个空餐的构造器,它呢都是确定下来的。
11:11
啊,就这里边呢,咱们把这个方法跟构造器呢就融到一起了,这个咱们在编写代码的时候哈,这个大家要清楚,咱们在编写代码的时候呢,或者说一开始讲Java的时候,咱们说构造器是构造器,方法是方法,两个呢是完全不同的概念,构造器是用来实例化的啊,方法呢是用来被类或者对象调用的,但是你看到我们在自解码文件中呢,是都放到这个方法这个结构里了。啊,这个你知道就行啊,知道就行,刚开始大家学的时候呢,还是把它认为是不一样的结构,包括呢,你看我们这个呃,API的时候,对吧,咱们随便呢举一个,比如说string那个类,这个类里边呢,你往下看,这呢就叫做属性,这呢就叫做构造器,下边这就叫做方法,也是完全分开的啊,只不过呢,大家呢,在熟练使用Java以后呢,呃,你知道磁解码文件当中,其实构造器跟方法呢就融到一起了,都叫做methods啊,都叫method是吧?有很多的methods呗,那相当于自行码文件里边是不是至少会有一个method呀。
12:14
因为你可以没有方法,但是肯定会有构造器,对吧,那至少会有一个method了,这就是两个构造器,那这两个构造器这两个位置呢,其实就体现了咱们叫哎,这叫早期绑定。这个跟咱们下边的一样啊,这个表现为早期绑定。行,那这呢,就大家对这个早期绑定,晚期绑定,诶有这样的一个理解,或者我们叫静态链接,这个动态链接是针对这个方法来说的啊,这个大家就能够清楚这个事了。啊,应该是比较清楚了啊,然后呢,咱们来看呃下边这个说法,呃,随着高级语言的横空出世等等这样,呃应该我们说啊,在这个Java语言出现之前,呃,咱们呢,说有这个面向过程的这个语言也算是高级语言呢,其中的一个阶段哈,是吧,面向过程的语言,那面向过程的语言严格上来说呢,它其实只有早期绑定,就是我们在编译期呢,就能够确定下来你到底调用的是哪个具体的结构了,哎,这个咱们下边这也表现为这个叫呃早期绑定是吧,就是在编译期呢,咱们就确定下来,那调的是这个。
13:26
编译起是吧,就确定下来你到底调的是哪一个方法,哪一个结构了,呃,就是由这个符号引用转换为了这个叫直接引用,呃,符号引用转化成直接引用,在编译起呢,就能确定下来啊这是咱们说面向过程的语言啊,只存在着早期绑定,但是呢,我们有了Java语言以后啊,以及呢,后来有各种各样的面向对象的语言,面向对象的语言呢,都有这个封装继承多态的这种共性,那尤其呢是具备了这个多态性,那自然而而然,自然而然像Java这样的语言呢,就具备了早期绑定和晚期绑定这样的两种方式,哎,这个大家清楚,呃,下边呢,是提到说这个Java中的任何一个普通的方法,其实都具备虚函数的特征,这个虚函数呢,特征就体现为就是我们在运行期才能够确定下来,其实呢,就是我们所说的具备这种晚期绑定的这种特点啊,那相当于呢,C加加语言中的这个虚函数,那C加加呢,我们说就具备了面向对象的这个特征了,只不过呢,C加加里边这个我们要想表示这种虚函数的需要用这个virtual这样。
14:26
的一个词来表示,像咱们刚才呢,在演示的过程当中,演示这不是了啊,咱们在演示刚才这个animal test这个位置的时候。点击一下,嗯,我们在这是吧,在在这在这吧。咱们看到这不就是一个引叫virtual嘛,哎,这就是virtual,你可以理解为跟我们这个virtual呢就对应的啊,刚才在这个位置呢,其实就体现了,就像是一个虚方法的一个调用了啊,包括在这呢也是一样,只不过这针对于接口呢,它叫做呃,In worker interface了啊,也算是虚方法这样一个特点,C加加里边呢,要想体验这种多态的特点呢,你需要用这种virtual这个关键字呢来表示,那Java呢,默认情况下呢都具备,除非呢,就是你要不想让它具备的话呢,咱们用final来修饰一个方法就可以了。
15:12
Final应该不陌生,那标识为final的方法呢,我们说就不能够被重写了是吧?不能被重写那就是在编译期就确定了啊,不具备这种多肽的这种特点啊,这个多肽呢,大家应该都不陌生啊,这个C加加里边这个虚函数就类似于咱们说的这个多态性啊,简而言之呢,就是允许父类的类型的这个指针呢,就指向你子类对象的这个实例,通过父类的这个指针,或者我们Java中叫做引用呢,诶这个当你实际执行的时候呢,调用的是子类重写的那个方法。对吧,重写的一个方法,这呢,就体现为咱们说叫多肽的一个理解啊,或者叫这里提到一个概念叫做虚函数,跟咱们这个多肽呢,是诶关联在一起的,那下面的话呢,咱们再专门的关于这个虚方法或者非虚方法,咱们再解释一下啊先停一下。
我来说两句