一、JVM和Java体系结构(16)


动态链接:
如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也就被称之为动态链接 。
对应的方法的绑定机制为:早期绑定(Early )和晚期绑定(Late ) 。绑定是一个字段、方法或者类在符号引用被替换为直接引用的过程,这仅仅发生一次 。
早期绑定:
早期绑定就是指被调用的目标方法如果在编译期可知,且运行期保持不变时,即可将这个方法与所属的类型进行绑定,这样一来,由于明确了被调用的目标方法究竞是哪一个,因此也就可以使用静态链接的方式将符号引用转换为直接引用 。
晚期绑定:
如果被调用的方法在编译期无法被确定下来,只能够在程序运行期根据实际
的类型绑定相关的方法,这种绑定方式也就被称之为晚期绑定 。
package com.lxg.java2;/*** 说明早期绑定和晚期绑定的例子* @author shkstart* @create 2020 上午 11:59*/class Animal{public void eat(){System.out.println("动物进食");}}interface Huntable{void hunt();}class Dog extends Animal implements Huntable{@Overridepublic void eat() {System.out.println("狗吃骨头");}@Overridepublic void hunt() {System.out.println("捕食耗子,多管闲事");}}class Cat extends Animal implements Huntable{public Cat(){super();//表现为:早期绑定}public Cat(String name){this();//表现为:早期绑定}@Overridepublic void eat() {super.eat();//表现为:早期绑定System.out.println("猫吃鱼");}@Overridepublic void hunt() {System.out.println("捕食耗子,天经地义");}}public class AnimalTest {public void showAnimal(Animal animal){animal.eat();//表现为:晚期绑定}public void showHunt(Huntable h){h.hunt();//表现为:晚期绑定}}
随着高级语言的横空出世,类似于Java一样的基于面向对象的编程语言如今越来越多,尽管这类编程语言在语法风格上存在一定的差别,但是它们彼此之间始终保持着一个共性,那就是都支持封装、继承和多态等面向对象特性,既然这一类的编程语言具备多态特性,那么自然也就具备早期绑定和晚期绑定两种绑定方式 。
Java中任何一个普通的方法其实都具备虚函数的特征,它们相当于c++语言中的虚函数(c++中则需要使用关键字来显式定义) 。如果在Java程序中不希望某个方法拥有虚函数的特征时,则可以使用关键字final来标记这个方法 。
8.1、虚方法和非虚方法
非虚方法:
虚拟机中提供了以下几条方法调用指令:
普通调用指令:
1.:调用静态方法,解析阶段确定唯一方法版本
2.:调用方法、私有及父类方法,解析阶段确定唯一方法版本
3.:调用所有虚方法
4.:调用接口方法
动态调用指令:
5.:动态解析出需要调用的方法,然后执行
前四条指令固化在虚拟机内部,方法的调用执行不可人为干预,而指令则支持由用户确定方法版本 。其中指令和指令调用的方法称为非虚方法,其余的(final修饰的除外)称为虚方法 。
package com.lxg.java2;/*** 解析调用中非虚方法、虚方法的测试** invokestatic指令和invokespecial指令调用的方法称为非虚方法* @author shkstart* @create 2020 下午 12:07*/class Father {public Father() {System.out.println("father的构造器");}public static void showStatic(String str) {System.out.println("father " + str);}public final void showFinal() {System.out.println("father show final");}public void showCommon() {System.out.println("father 普通方法");}}public class Son extends Father {public Son() {//invokespecialsuper();}public Son(int age) {//invokespecialthis();}//不是重写的父类的静态方法,因为静态方法不能被重写!public static void showStatic(String str) {System.out.println("son " + str);}private void showPrivate(String str) {System.out.println("son private " + str);}public void show() {//invokestaticshowStatic("atguigu.com");//invokestaticsuper.showStatic("good!");//invokespecialshowPrivate("hello!");//invokespecialsuper.showCommon();//invokevirtualshowFinal();//因为此方法声明有final,不能被子类重写,所以也认为此方法是非虚方法 。//虚方法如下://invokevirtualshowCommon();info();MethodInterface in = null;//invokeinterfacein.methodA();}public void info(){}public void display(Father f){f.showCommon();}public static void main(String[] args) {Son so = new Son();so.show();}}interface MethodInterface{void methodA();}