Java中的绑定

1 前言

作了一次笔试题,发现了一题问答题,是关于Java绑定的:html

在这里插入图片描述

当时作的时候是彻底不会的。。。java

因而这里补上一篇Java绑定的文章。app

2 绑定

首先来了解一下绑定的概念。绑定是指一个方法的调用与方法所在的类关联起来jvm

很抽象吧,举个例子,若是父类与子类存在同名方法,子类对父类方法进行了重写,那么就须要绑定来区分调用的究竟是父类的方法仍是子类的方法。相对简单的一种理解是,绑定是一个方法的调用与调用这个方法的类链接在一块儿的过程。ide

而绑定具体又能够分为:spa

  • 静态绑定:就是程序执行前,方法已经被绑定,能够简单理解成编译期绑定
  • 动态绑定:在运行时根据具体对象的类型进行绑定,经过一些机制去运行时判断对象的类型,并分别调用适当的方法

3 静态绑定

静态绑定也叫前期绑定、编译期绑定,在程序运行以前,也就是编译时期JVM可以确认方法由谁调用,这种机制就叫静态绑定。code

若是一个方法由privatestaticfinal任意一个关键字修饰,那么这个方法就是静态绑定的,缘由很简单,由于:htm

  • private修饰的方法,没法由本类之外的类调用,也就是调用者只能是该类
  • static修饰的方法,经过类名.方法名进行调用,也能够惟一肯定了调用的类
  • final修饰的方法,不能被子类进行重写,在编译期就能肯定了调用的类

这三个关键字修饰的方法,均可以在编译时期就能惟一肯定了调用的类,不存在子类调用的问题,所以使用静态绑定,而不是动态绑定。对象

4 动态绑定

动态绑定就是运行时根据对象的类型进行绑定,简单来讲,JVM在运行时期决定由哪一个对象调用的过程称为动态绑定。blog

好比:

public class Main {
    public static void main(String[] args){
        A b = new B();
        b.print();
    }
}

class A{
    public void print(){
        System.out.println("A");
    }
}

class B extends A{
    @Override
    public void print(){
        System.out.println("B");
    }
}

因为B类继承了A类,所以建立对象的时候:

A b = new B();

编译期并不知道b真正引用的是A类仍是B类,在运行的时候才知道b是一个A类对象,可是指向了B类的引用。

Java中,全部的非finalprivatestatic的方法都是动态绑定的,由于只要继承了就能重写。

5 区别

  • 发生时期:静态绑定发生在编译时期,动态绑定发生在运行时期
  • 灵活性:动态绑定的灵活性要比静态绑定高,由于静态绑定在编译的时期就肯定了,而动态绑定在编译的时候并不知道是调用哪个类的方法
  • 速度:静态绑定调用方法的速度要快于动态绑定,由于静态绑定能够直接调用,而动态绑定须要去搜索方法表

6 动态绑定的过程

在了解动态绑定的过程以前,先了解一些前置知识。

6.1 方法调用

Java中的方法调用有两类:

  • 静态方法调用
  • 动态方法调用

而方法调用的指令有四个,分别是:

  • invokestatic
  • invokespecial
  • invokevirtual
  • invokeinterface

前两个是静态绑定的,然后两个是动态绑定的。

6.2 方法表

方法表是字节码文件的一部分,每一个类都有一个方法表,方法表是为invokevirtual以及invokeinterface指令服务的。因为Java中的类都继承于Object,所以,在默认状况下,全部类的方法表中都有Object的方法,若是重写了其中的方法,就会改变其中的描述符。好比,Object类的方法表能够简单理解以下:

在这里插入图片描述

而加载了A类的字节码后,由于A类并无重写任何的Object方法,所以只是添加了A类自己的方法:

在这里插入图片描述

而加载了B类的字节码后,由于重写了print(),所以方法表以下:

在这里插入图片描述

6.3 具体过程

了解了前置知识后看具体过程就会相对简单一点了,动态绑定的过程能够分为三步:

  • 虚拟机提取对象实际类型的方法表:JVM获取到对象的实际类型后,再获取该类型的方法表
  • 虚拟机搜索方法签名:当调用b.print()时,经过方法表发现实际方法是B.print()
  • 调用方法:调用B.print()

7 参考

相关文章
相关标签/搜索