静态绑定和动态绑定

一、绑定

  一个方法与类/对象联系起来。

二、静态绑定

  如果是private、static、final方法,编译器可以准确的指导应该调用哪些方法,因为子类是不能重写这些方法的,这种调用方法称为静态绑定(static binding)。

三、动态绑定

  调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定。

四、动态绑定过程

  虚拟机先在该对象的类中寻找是否有该方法,如果有直接调用,如果没有则在超类中寻找。但如果每次调用方法都要进行搜索,时间开销会相当大。因此虚拟机为每个类预先创建了一个方法表,其中列出了所有方法的签名和实际调用的方法。
  Employee.java

 1 package test;
 2 import java.time.*;
 3 public class Employee {
 4     private String name;
 5     private double salary;
 6     private LocalDate hireDay;
 7 
 8     public Employee(String name, double salary, int year, int month, int day){
 9         this.name = name;
10         this.salary = salary;
11         this.hireDay = LocalDate.of(year,month,day);
12     }
13 
14     public Employee(){
15 
16     }
17     public String getName() {
18         return name;
19     }
20 
21     public double getSalary() {
22         return salary;
23     }
24 
25     public LocalDate getHireDay() {
26         return hireDay;
27     }
28 
29     public void raiseSalary(double byPercent) {
30         double raise = salary * byPercent / 100;
31         salary += raise;
32     }
33 
34 
35 
36 }

  Manager.java:

 1 package test;
 2 
 3 public class Manager extends Employee {
 4     private double bonus;
 5     public Manager(String name,double salary, int year, int month, int day){
 6         super(name,salary,year,month,day);
 7         bonus = 0;
 8     }
 9 
10     public Manager(){
11     }
12     
13     @Override
14     public double getSalary() {
15         double baseSalary = super.getSalary();
16         return baseSalary +bonus;
17     }
18 
19     public void setBonus(double b){
20         bonus = b;
21     }
22 }

  main.java

 1 package test;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         Manager boss = new Manager("Carl",8000,1987,12,15);
 6         boss.setBonus(5000);
 7         Employee[] staff = new Employee[3];
 8         
 9         staff[0] = boss;
10         staff[1] = new Employee("Harry", 5000, 1989, 10, 1);
11         staff[2] = new Employee("Harry", 4000, 1990, 3, 15);
12     
13         for(Employee e : staff)
14             System.out.println("name="+e.getName()+",salary="+e.getSalary());
15     }
16 
17 
18 }

  在main.java第14行调用e.getSalary()的过程:

  • 由于getSalary不是private、static或final方法,所以将采用动态绑定。
  • 虚拟机预先为Employee何Manager两个类生成方法表。
    Employee:
      getName()  ->  Employee.getName()
      getSalary()  ->  Employee.getSalary()
      getHireDay()  ->  Employee.getHireDay()
      raiseSalary(double)  ->  Employee.raiseSalary(double)
    Manager:
      getName()  ->  Employee.getName()    (Manager没有,从父类继承)
      getSalary()  ->  Manager.getSalary()  (重写了)
      getHireDay()  ->  Employee.getHireDay()
      raiseSalary(double)  ->  Employee.raiseSalary(double)
      setBonus(double)  ->  Manager.setBonus(double)     (Manager的方法)

    注意:这里的方法表省略了Object类的方法,所有的类都继承自Object类
  • 首先虚拟机提取e的实际类型的方法表。既可能是Employee、Manager的方法表,也可能是Employee类的其他子类的方法表(本例中staff[0]是Manager,staff[1]、staff[2]是Employee)。
  • 接下来,虚拟机搜索定义getSalary签名的类。调用该方法。
上一篇:lambda


下一篇:Zabbix中Agent自动注册