00:00
好,下面呢,咱们来专门说明一下这个虚方法和废虚方法,这个呢,在咱们Java中的这个多肽当中是提到过这样一个概念啊,多肽呢,我们说当你声明了一个父类的引用以后,我们在真正执行的时候呢,传入的是一个子类的一个对象,诶我们调用这个E的方法呢,其实它表现为就是子类重写的方法了,哎,这儿呢,其实就存在的一个续方法的一个调用,那什么叫续方法,续方法呢,其实就跟咱们刚才说对应的这个动态绑定,或者叫呃,不是动态绑,这个晚期绑定,或者叫动态链接呢,是对应的,就是我们在这个编译期呢,没法确定此方法是哪一个具体类的方法,执执行的是哪个类的方法,只有在运行期间呢才能够确定啊,晚期绑定或者叫动态链接对吧,那下边呢,咱们来说明一下这个方需方法和废墟方法哈,首先呢,我们先说一下这个叫飞序方法。说呀,如果在这个编译期间就确定了具体的调用版本,这个版本呢,在运行期间呢,还是不变的,这就成为飞序方法啊,跟咱们之前描述这些类似的,叫早期绑,早期绑定,或者叫静态链接等等都是对应的,那什么样的方法具备这样的特点呢?说静态方法,私有方法哎,或者叫final的方法,实力构造器负类方法哎,都是属于非虚方法,就是这块呢,大家有一个小技巧,就是你理这个理解这个分析方法的时候呢,因为它在编译期间就确定下来了,所以不涉及到这种多态的形式啊,比如说呢,咱们讲这个,呃,这个静态方法啊,一说到多肽呢,咱们还得再提到一个概念,就是方法的一个重写是吧,就是咱们写写到这儿吧,算是一个小的一个复习哈。
01:42
哎,我就写到这儿了,这个多肽呢,我们说它的一个使用前提。呃,使用前提呢,呃,一个呢,是有我们这个继承关系是吧,类的继承关系就我们更多说,我们现在说的是子类对象的这个多态性啊,子类对象的多态性。
02:06
多肽性的。使用前提,它呢,第一个是聚丙类的关系,呃类的继承关系,我们声明呢,是一个父类的真正创建对象呢,是一个子类对象,这叫集承关系这块第二呢,就有方法的一个,呃重写这呢才能够呃达到我们这个多态性的一个特点啊,就是我们真正执行的是子类重写的方法,如果呢,你要是没有重写的一个方法,那跟我们造的是一个父类对象还是这个子类对象,其实就没有关系了,那这个类继不继承呢,也无所谓了,就没有必要非得体现这种多态的特性了,对吧?那这儿呢,我们主要呢,是想说的是这个第二点啊,咱们在实际开发中,这不也有大量的情况,咱们呢是接口,真正你执行的时候呢,导入第三方的炸包,然后呢,编写代码的时候呢,呃,写的是接口中的重要方法,但真正运行的时候呢,都是第三方炸包当中的人家重写的这个方法了,哎,都体现为这个方法的重写,那现在呢,我们说这个分析方法呢,就跟咱们这个多态性正好是相抵触的。
03:03
或者说呢,叫虚方法跟我们这个多态性是这个有对应关系的啊,那分析方法呢,这块呢,就跟我们这个方法的重写是抵触的,那比如说像我们所谓的这个静态方法,咱们认为静态方法是不可以被重写的,对吧,私有方法呢,也不能够被重写。Final的方法呢,那更不能被重写,加final呢,就表示它不能被重写了,呃,那这三个呢,就非常明确,就是它呢,就是非常确定的了,不会说指向又是子类重写这个方法了,所以静态私有final的方法呢,诶他们就是分析方法,非常好理解啊,然后后面呢,说叫实力构造器,咱们说这个在当前这个类当中,当前这个类当中我这有构造器,只有构造器,如果我通过这次的方式呢,调用本类中重载的其他构造器了,那这时候呢,显然也是非常确定掉的是哪一个构造器方法,所以呢,这个构造器呢,这块也叫废墟方法。因为咱们这构造器这块叫重载不叫重写了是吧?诶这个或者说构造器本身也不能重写嘛,构造器不能被重写对吧?诶所以说呢,这块也理解为就不能被重启了,也是非序方法,然后下个呢叫做父类方法,就是如果我们明确啊,比如说呢,咱们上边是父类,下边是子类,然后然后这个呢叫方法A,然后呢,咱们子类呢,把这个方法A呢做了一个重写,在这个方法A当中,子类的方法A中,咱们显示的通过super点的方式调用父类这个方法A了,那这呢也认为你是非常确定的某一个方法,就是负类的这个A方法,所以呢,也认为是非虚方法。
04:35
诶非常清楚,大家把这个呢记一下,那么除了这些之外呢,剩下的这种方法呢,我们就认为是虚方法了,说白了就是剩下这种情况,我们不确定到底调的是哪一个,呃,子类啊,父类啊,这个方法的我们就称为叫虚方法。诶,就称为叫虚方法啊,那下边这我也写了个代码,大家可以不用看这个例子了,咱们直接在这个呃idea当中看一个例子啊,那这样呢,咱们再结合这几个指令来说,再结合几个指令来说,那么在虚拟当中啊,咱们提供了关于方法调用的几个指令,普通的调用指令呢,有invoke static invoke special invoke virtual和invoke interface,刚才咱们在演示上一个例子当中呢,大家应该见到了呃其中的这样的几种情况了啊这块呢,还多了一个在JDK7当中新增加的叫VO dynamic,呃,这块呢,其实主要体现了我们这个Java这个语言的一定的这个叫呃动态性是吧?呃,一会咱们再专门说一下这个VO dynamic的这个情况啊,那咱们先来关注上边这四种情况。
05:40
上面四种情况后边呢,就指明了在什么情况下啊,调用什么样的方法,使用的是这样的一个指令啊,这里边这个两个蓝色的大家看到啊,这两个蓝色的呢,它对应的这种,诶这个指令其实对应的都是非虚方法,哎,我们看这写着的invoke static invoke special它们呢,都是非虚方法,哎,这两个是非常明确的,那这两个是不是对应的都是虚方法呢?呃,其实不太。
06:13
完全正确哈,呃,抠出去谁呢?调用的所有的虚方法,其实这块我们要把谁抠出,要把这个final抠出去,Final的这个方法在调用的时候呢,它也是叫in work出了,但其实它是确定的了,哎,这个把它也抠出去以后,诶剩下呢都称为叫虚方法,哎这样子的啊呃,行,那咱们这块呢,把这几种情况呢,给大家演示一下啊,演示一下,那咱们看一下这里边的一个程序,咱们就看下一个啊,这个叫丧,诶在这个程序当中,首先呢,来解释一下这个程序啊,我们主要来看一下这个虚方法啊和分析方法的一个测试了。负类呢,我这叫father,这呢有一个构造器,诶这呢,我在负类当中定义了静态的方法,Final的方法,还有普通的一个方法,哎,普通的一个方法,好,这是我们父类中定义的,包括扩造器在内啊,这个算式有四个,编译以后呢,是有四个方法,OK,然后呢,我们在这个子类当中。
07:11
哎,子类当中我们看一下啊,这个首先呢,我们定义了两个构造器啊,定义两构造器,然后呢,我们在这个子类里边,我也定义了一个死代的一个方法,这个权限返回值类型,这个方法名行参列表跟咱们附类这个是一样的的,但是你注意我们说静态方法是不可以被重写的,所以这个方法呢,我们在这儿明确一下啊,呃,不是重写的负类的方法。呃,因为静态方法呢,不能被重写。那这要注意啊行,然后下面呢,我们在这个子类当中呢,又定义了一个私有的方法啊,私有的方法OK,然后整个这个特点呢,咱们在这个数里边呢,去体会一下。诶,受里边来体会一下,好在受里边呢,你看我这块呢,调用了这样的一些这个结构哈,嗯,我瘦死static这儿呢,咱们是没有加上前面谁来调,其实就默认是Z4点了,那调的其实就是咱们子类自己的这个受死sta这个这样的一个方法,调的是自己的啊,这是它,呃,然后呢,我们下边这个super点瘦static呢,我调的是负类中的。
08:21
这个show static看我们在点击按钮的时候呢,就跑到这来了,编译的时候认为是负类的,真正我们运行的时候,这个咱们可以跑一下啊,你看我在这没方法当中,我这就调了一下这个收方法,看一下前两行。跑一下。诶好了,诶,下边报这个异常是因为我后边这有一个接口没有实例化报异常啊,这个大家不用管,那我们看上边这块,诶发字的构造器,这呢是咱们在造对象的时候,我在这块是new对象是吧?呃,调用呢是副列构造器了啊,所以这个先忽略掉啊,然后看这两行,这两行对应的。
09:00
在这啊,这个代码对应的就是我们这个操作。然后呢,这个修点呢,对应的就是咱们这个操作,诶通过呢,你看它这个打印的信息呢,你就能看出来,一个呢是子类的,一个是父类的,嗯,你会发现呢,咱们编译的时候跟运行时候呢,这都是确定的啊,就是都是呃调的子类的父类的运行时候也是这样子的,实际上它们都是非虚方法啊,然后呢,受private按照我们刚才理解呢,调用私有方法,它自己的也是非虚方法,然后下边呢,是咱们显示的调用了负类的这个方法了。显示调用负类的这个受common方法,就是负类中的一个普通方法,这其实也应该是一个分析方法,好,那说到这儿呢,咱们就在这儿是吧,诶先呢,我们看一看这个情况啊,呃,自动呢,它就保存了,然后我们先做一个重新的编译。编译完以后以后呢,我们主要呢,来看一下这个song这个类,它的一个字节码的一个解析的情况,好打开以后我们看一下这个method啊,Method里边诶,包括这个构造器也是一样,咱们等一下再说构造器啊看这块受首先呢,我们看它的受里边打开扣的啊,这个代码量会稍微的大一些。
10:17
首先呢,你看我们这个叫show static,呃,其实对应的就是我们这个操作了,它调用的是我们自己这个类中的这个show static,呃,所以这块呢,你看这个指令呢,叫呃引物s static,嗯,是它对吧,诶我们CTRLC一下啊。诶,Invo克static,然后下边这个呢,我们调的是副类当中的静态方法,也是invo static,就是调用的这个静态方法都认为,那这两个都认为它是非虚方法啊,然后再往下呢,我们是收private,收private这个应该是我们这个13行了,看一下诶,确实是private,这呢叫invoke special,诶这个呢,也是我们说的一个虚拟非虚方法的一个指令。
11:03
OK,然后下边这个呢叫是呃修点受common,呃显示的调用负类中的这个方法了,嗯,应该是在应该是这个第17行了啊,看一下是不是17。受common OK负Z的这个这呢也是叫invo special。行,那这几个的话呢,你看VO staticvo special跟我们这块说到的这两个是一样的,就是它调用的都算叫飞絮方法的这个指令,也就是说呢,在编译期间就能够确定的。啊,那除了这个之外呢,我们说构造器这块呢,也是一样的啊,你看我们这个呃,子类sun当中,它呢首次呃首行呢调用super,然后呢,你也可以在自己的构造器中呢,调本类中重载的其他构造器,那我们看上边这两个,那第一个呢,这叫invo special也是这样的一个指令,然后看下边这个。
12:00
呃,也是invoke special调用了它自己类中的这个in这个,呃,构造器方法啊,就是这两个呢,都是叫invo special,也就是说呢,咱们刚才看到的这些凡是写了invo static和invo special的,哎,这呢都属于非虚方法调用的指令。啊,这个我们在这说明一下,那其实就是我们PPT里边在这写的啊,说invoke static和invo special的调用的这个指令,调用的这个方法呢,就称为叫虚方法。非虚方法,嗯,这样的情况啊,行,那咱们呢,再接着往下看,接着往下看的话呢,这我有一个叫show final啊,Show final final呢,是我们在负类当中那定义的这样的一个方法,诶这呢,我叫show final啊,然后这个方法的话呢,你看前面我是没有给它加上super点的,没有加super点的情况下呢,我们看一下这个瘦。
13:04
Final。Final在这儿啊,大家看到此时呢,它叫invoke,呃,Virtual,呃,Invo virtual呢,按照我们的理解,这就算是叫虚方法一样了,是吧?呃,看似呢像这个续方法了,但其实这个呢,我们对应的咱也都知道啊,这个show final,这个final的方法是不能够被重写的了,哎,不能被重写了,虽然它叫程是virtual,但是呢,这个我们也不认为它就是一个虚方法,因为呢,你子类也不可能再有这个重写的这个方法了,对吧?那如果我们前面加上一个super点呢?那就是显示的调用的是父类这个方法了,我们看看这个时候呢,会不会有不同,重新呢编译一下。呃,编译完以后呢,我们过来再做一个刷新,刷新这时候我们再来看这个show,呃,我们看一下这个show final啊,这个时候呢,它就要VO special了,诶就是相当于是有了一个变化啊,因为呢,咱们显示的给它加上了super点,它就明确是一个复类的方法了,所以呢,它显然就就是更更明确的,从指令上看,它就是一个飞序方法,对吧?但是呢,我们这时候如果要是没有加这个super点,其实它也必须是负类的,因为它本身也不能够被冲写,所以这里边呢,虽然我们叫做呃,这个invo water,但是你要注意这个调用的,那这样说哈,呃,因为此方法是。
14:29
诶,或者叫声明有final,哎,不能被子类重写,哎,所以呢。哎,所以啊,也认为。那此方法是非这个虚方法,就是它其实也是确定的啊,我们所谓的虚方法呢,指的是在编译期间没法确定下来的,我们才叫做虚方法。啊好,这个就过了啊嗯,那刚才稍微改过这个代码呢,不妨咱们就再重新编一下啊,确保咱们这个程序呢,咱调的这时候呢,都是真实的啊,跟这个最码指令都能对应起来,然后呢,刷新以后咱们再回过来看这个扣的。
15:10
哎,那这时候呢,我们这个final这块看又是一个watch了啊,然后再往下呢,叫show common,诶受common大家看啊,这个受common呢,咱们上边也调过此类呢,也没重写过。看没有重写过啊,掉的其实就是负类的这个方法,但是呢,由于你没有显示的加super点,其实跟咱们刚才上面这个类似啊,你没有显示加super点呢,所以他就认为你是个续方法,因为呢,有可能咱们当前这个子类。有可能咱们当年这个散这个子类是不是它会重写这个手拷门对吧?诶那你要你重写的话,它它不就是表现成子类的特性了嘛,所以这个呢,在编译期间呢,我们认为是确定不下来的啊,真正运营时候呢,我们才能确定下来,所以它是一个虚方法,然后再往下这个infer,嗯,这个infer呢iner iner iner有啥特别呢。
16:02
诶是咱自己定义的,那自己定义的这个方法的话呢,诶它这个也指明的是一个,哎龌臭是这样的一个方法啊行这儿呢,就是咱们说的这个,呃,续方法的这个情况。哎,这样一个情况,嗯,那不仅如此,你看我们下边这块这个method的interface,这是咱们定义的一个接口,这个接口里边有个出方法,然后我这块呢,就是没有明确去赋值给它实例化了,然后调一下这个method a,那这个method a呢,是一个抽象方法,这个方法的话呢,你真正咱们说你要想运营时候执行成功,那肯定是需要去重写了,那你重写的时候呢,我就不知道你的子类到底是什么对吧?所以这个时候呢,它表现为呢,是这样的一个叫invoke interface,就是调用的是接口中的这个方法,那那这个方法呢,在真正执行的时候,我们肯定是需要被重写了,对吧?那所以说我们这个invoer interface呢,它也体现为是虚方法的一个情况。
17:03
因为编译和运行它编译你认为你看我这一点是不是认为成接口里的,但实际上我们要执行的话呢,是你呃重这个实现的这个子类,呃实呃实这个实现类里边这个重写的这个方法,或者我们准确的说,准确的说呢,像这个实现类里边我们应该叫这个实现的这个接口中的方法了,是吧,哎就不叫重写这个词了啊,叫实现的方法,那这呢就体现为这种多态的特性,哎也称作叫做呃虚方法的一种情况啊行,那刚才呢,咱们就把这四种指令呢,给大家一一呢做了演示,大家对这个序方法和飞序方法呢,应该有一个比较清晰的一个认识啊,理解了。
我来说两句