关于 java 的动态绑定机制

聊一聊动态绑定机制, 相信看完这篇文章,你会对动态绑定机制有所了解。

网上大多一言概括:

当调用对象的时候,该方法会和该对象的内存地址/运行类型绑定。

当调用对象的属性时,没有动态绑定机制,哪里声明就使用哪里。

这里我们展开来说一说。

动态绑定机制,简单来说,就是在以父类为编译类型,创建子类对象的时候,绑定子类运行类型,当我们再调用方法的时候,能够有序的寻找方法,实现方法的有序调用。

动态绑定机制会出现在多态中,多态是 Java 的重要的三个属性之一,动态绑定机制就是建立在,封装,多态,继承的基础上延伸出的。

要了解动态绑定机制,首相要把对象的多态与继承搞明白,还有编译类型,运行类型,这是前提。网上都有详细的讲解,这里不做延伸。

废话不多书,直接上代码演示讲解,详细的讲解会在代码的注释当中。

首先我们要 创建父类 Person 类

//创建父类
public class Person {
    //简单的创建两个属性
    private String name;
    private int age;

    //创建行为方法,方法中调用创建的say方法
    public void haviours(){
        say();
    }
    //创建方法
    public void say(){
        System.out.println("我是人类!!!");
    }

}

创建子类 Student

//创建子类
public class Student extends Person {
    //创建学生的属性
    private int  score;
    //重写行为
    public void haviours(){
        say();
    }
    //重写say方法
    public void say(){
        System.out.println("我是学生!!!");
    }
}

首先我们对 say 方法进行调用。

public class Demo01 {
    public static void main(String[] args) {
        //创建学生
        Person student = new Student();
        //调用学生的say()方法,由于我们的编译类型是Person类,而运行类型是Student类,而动态绑定机制是绑定运行类型。
        //所以,当我们调用say()方法时,是调用Student类的say()方法
        student.say();//返回“我是学生”
        //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
        //如果我们将student类的say()方法注销,他寻找student类的say方法无果后,会再向它的父类调用say方法。返回我是人类,效果等同于

    }
}

但是,重点来了。。。。。。。。。。。。

如果我们调用的是 haviours 方法,那么他的方法是调用什么呢

public class Demo02 {
    public static void main(String[] args) {
        //创建学生
        Person student = new Student();
        //调用学生的haviours方法,由于我们的编译类型是Person类,而运行类型是Student类,而动态绑定机制是绑定运行类型。
        //所以,当我们调用haviours()方法时,该对象绑定的是Student类,所以是调用Student类的say()方法
        student.haviours();//返回我是学生!!!
    }
}

但是,还有人可能会有疑问,如果 Student 类中的 havious 方法被注释掉呢,你是不是会想。子类 Student 中没有 havious 方法,调用父类的 havious 方法,然后 havious 调用父类的 say 方法???

抱歉了,他调用的是子类 Student 的 Say 方法

public class Demo03 {
    public static void main(String[] args) {
        //创建学生
        Person student = new Student();
        //调用学生的haviours方法,由于我们的编译类型是Person类,而运行类型是Student类,而动态绑定机制是绑定运行类型。
        //所以,当我们调用haviours()方法时,由于子类没有havious方法,调用父类的havious方法,在父类的havious中,调用say方法,这时,动态绑定机制是绑定运行类型。该对象绑定的是Student类,所以是调用Student类的say()方法
        student.haviours();//返回我是学生!!!
    }
}

介绍完动态邦迪机制对方法的绑定,接下来说一说对属性的影响。

当调用对象的属性时,没有动态绑定机制,哪里声明就使用哪里。这句话十分容易理解。

也就是动态绑定机制对属性没有影响,放心调用。

动态绑定机制(完)。

结语:由于在网上查找相关的动态绑定机制时,看到没有动态绑定的详细讲解,而这也是一个小难点,所以翻阅书籍,进行了学习,并进行总结,世界上本没有路,走的人多了,也便有了路。

欢迎大家关注公众号「马小乐学技术」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考、面经资料等等,同时欢迎大家加我微信「sy200316x」一起交流学习 

### Java动态绑定原理 Java 中的动态绑定是一种运行时机制,用于决定调用哪个方法版本。这种机制基于对象的实际类型而不是引用类型来执行方法调用[^1]。换句话说,即使一个父类类型的引用指向了一个子类的对象实例,实际调用的方法将是子类重写后的版本。 #### 动态绑定的核心特点 - **多态支持**:动态绑定是实现多态的关键所在。通过动态绑定,程序可以在运行时根据对象的实际类型调用相应的方法。 - **适用范围**:动态绑定仅适用于实例方法,而不适用于 `static` 方法、`final` 方法以及 `private` 方法。这是因为这些方法要么无法被继承(如 `private`),要么在编译期就已经确定其行为(如 `static` 和 `final`)[^2]。 - **JVM 实现**:动态绑定JVM 自动完成,开发者无需手动干预。具体而言,JVM 使用虚方法表(vtable 或 method table)记录每个类及其对应的方法地址,从而快速定位并调用正确的方法[^3]。 --- ### 示例代码展示动态绑定过程 以下是关于动态绑定的一个经典例子: ```java // 定义父类 Animal class Animal { public void makeSound() { System.out.println("Some generic sound"); } } // 定义子类 Dog 继承自 Animal 并重写方法 class Dog extends Animal { @Override public void makeSound() { System.out.println("Bark Bark!"); } } public class Main { public static void main(String[] args) { // 向上转型:父类引用指向子类对象 Animal myPet = new Dog(); // 调用 makeSound 方法,尽管引用类型为 Animal, // 但由于动态绑定的存在,实际上会调用 Dog 的实现 myPet.makeSound(); // 输出 "Bark Bark!" } } ``` 在这个示例中,虽然变量 `myPet` 是 `Animal` 类型的引用,但它指向的是 `Dog` 对象。因此,当调用 `makeSound()` 方法时,JVM 会查找 `Dog` 类的具体实现而非 `Animal` 类的默认实现[^4]。 --- ### 关键字解析与注意事项 - **向上转型**:指将子类对象赋值给父类引用的行为。这是动态绑定的基础条件之一。 - **向下转型**:如果需要访问子类特有的功能,则可以通过强制类型转换的方式恢复原始类型。需要注意的是,这可能会引发 `ClassCastException` 异常,除非事先确认对象的真实类型。 - **性能影响**:动态绑定引入了一定程度上的开销,因为每次都需要查询 vtable 来找到最终的目标方法。然而,在现代 JVM 中,这一操作已被高度优化,通常不会成为瓶颈。 --- ### § 1. 如何利用反射技术绕过动态绑定? 2. 在什么情况下应该避免使用动态绑定以提高效率? 3. 如果某个方法既标记为 final 又被子类尝试覆盖会发生什么情况? 4. 解释一下为什么 private 方法不属于动态绑定范畴内的原因是什么? 5. Java 字节码层面如何区分 invokespecial 和 invokevirtual?
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值