java 静态绑定_Java之动态绑定与静态绑定

本文详细介绍了Java中方法调用的静态绑定和动态绑定概念。静态绑定在编译时确定,如重载方法;动态绑定在运行时根据对象实际类型决定,如重写方法。通过实例分析了两者在多态和向上转型中的应用,强调了动态绑定在实现多态中的关键作用。
摘要由CSDN通过智能技术生成

1、当子类和父类存在同一个方法,子类重写了父类的方法,程序在运行时调用方法是调用父类的方法还是子类的重写方法呢?

2、当一个类中存在方法名相同但参数不同(重载)的方法,程序在执行的时候该如何辨别区分使用哪个方法呢?

在Java中我们使用静态绑定(static binding)和动态绑定(Dynamic binding)来解决,那么什么是绑定?什么是静态绑定?什么又是动态绑定?有什么区别?

绑定、静态绑定、动态绑定的概念

绑定

绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。

对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定。

静态绑定

在程序执行前方法已经被绑定,针对java简单的可以理解为程序编译期的绑定;

java当中的方法只有final,static,private和构造方法是前期绑定

动态绑定

在运行时根据具体对象的类型进行绑定。提供了一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。

动态绑定的过程:

虚拟机提取对象的实际类型的方法表;

虚拟机搜索方法签名;

调用方法。

静态绑定 VS 动态绑定

1、静态绑定是发生在编译阶段;而动态绑定是在运行阶段;

2、private, final and static方法和变量使用静态绑定,而虚函数(virtual methods)则会根据运行时的具体对象进行绑定(注:在Java语言中, 所有的方法默认都是”虚函数”。只有以关键字 final 标记的方法才是非虚函数。)

3、静态绑定使用的是类信息,而动态绑定使用的是对象信息

4、重载方法(overloaded methods)使用的是静态绑定,而重写方法(overridden methods)使用的是动态绑定

下面从代码中分析

静态绑定

public class StaticBindingTest {

public static void main(String args[]) {

StaticBindingTest sbt = new StaticBindingTest();

sbt.test("This is a String");

sbt.test(10);

}

public void test(String s) {

System.out.println(s);

}

public void test(int a) {

System.out.println(a);

}

}

输出结果

This is a String

10

从上面的结果可以得出:

在两个同名但参数不同的方法(重载),在调用方法sbt.test(param)时,程序会自动根据输入的参数类型来选择具体调用哪个方法,其后的原理就是静态绑定,即在编译期根据参数类型进行静态绑定。

java当中的向上转型或者说多态是借助于动态绑定实现的,所以理解了动态绑定,也就搞定了向上转型和多态。

动态绑定的典型发生在父类和子类的转换声明之下:

比如:Parent p = new Child();

其具体过程细节如下:

1:编译器检查对象的声明类型和方法名。假设我们调用p.method()方法,并且p已经被声明为Child类的对象,那么编译器会列举出Child类中所有的名称为method的方法和从Child类的父类继承过来的method方法

2:接下来编译器检查方法调用中提供的参数类型。如果在所有名称为method 的方法中有一个参数类型和调用提供的参数类型最为匹配,那么就调用这个方法,这个过程叫做“重载解析”

3:当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同p所指向的对象的实际类型相匹配的方法版本。假设child类定义了mehod()那么该方法被调用,否则就在child的父类(Parent类)中搜寻方法method()

动态绑定

子类有父类的重写方法

//父类

public class Parent {

protected String name = "ParentName";

public void method() {

System.out.println("ParentMethod");

}

}

//子类

public class Child extends Parent {

protected String name = "ChildName";

public void method() {

System.out.println("ChildMethod");

}

public static void main(String[] args) {

Parent p = new Child();

System.out.println(p.name);

p.method();

}

}

输出结果

ParentName

ChildMethod

子类中没有父类的重写方法

//测试类

public class DynamicBindingTest {

public static void main(String[] args) {

Parent p = new Child();

System.out.println(p.name);

p.method();

}

//父类

class Parent {

protected String name = "ParentName";

public void method() {

System.out.println("ParentMethod");

}

}

//子类

class Child extends Parent {

protected String name = "ChildName";

输出结果:

ParentName

ParentMethod

从上面的结果中可以看出:

1、子类的对象(由父类的引用handle)调用到的是父类的成员变量,运行时(动态)绑定针对的范畴只是对象的方法,而属性要采取静态绑定方法。

2、执行p.method()时会先去调用子类的method方法执行,若子类没有则向上转型去父类中寻找。

所以在向上转型的情况下,对象的方法可以找到子类,而对象的属性还是父类的属性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值