首页 > 编程语言 >java中的静态绑定与动态绑定

java中的静态绑定与动态绑定

时间:2024-11-13 22:40:25浏览次数:1  
标签:绑定 java 静态 子类 void Object 方法 public

个人学习记录,欢迎大家指导

什么是多态?

一个引用变量,它可以引用任何子类的对象,这个引用变量是多态的。

绑定

将一个方法调用与对应方法主体关联起来被称为绑定。(也就是,执行一条方法调用语句时所对应执行的方法体,叫做该方法体和这条方法调用语句绑定了)

动态绑定

来看一段代码

public class Parent {

    public void m(){
        System.out.println("父类方法执行");
    }

    public static void main(String[] arg){
        List<Parent> list = Arrays.asList(new A(),new B(),new C());
        for(Parent p : list){
            p.m();
        }
    }
}

class A extends Parent{
    public void m(){
        System.out.println("A类方法执行");
    }
}

class B extends Parent{
    public void m(){
        System.out.println("B类方法执行");
    }
}

class C extends Parent{
    public void m(){
        System.out.println("C类方法执行");
    }
}

output:
A类方法执行
B类方法执行
C类方法执行

何为动态绑定?
上述代码中,第一次循环,p变量接受一个A对象,p.m()语句调用A的m()方法,第二次循环时,p变量接受一个B对象,p.m()语句调用B的m()方法,第三次循环时,p变量接受一个C对象,p.m()语句调用C的m()方法,3次循环都是执行的p.m()语句,每次循环p.m()语句绑定的方法体不一样,这种运行时根据变量p实际引用对象动态绑定方法体的方式,叫做动态绑定。动态绑定是为了执行子类重写的方法。

静态绑定

对于static、final、private修饰的方法,以及构造方法,这些方法不可被子类重写,它们采用静态绑定。

方法调用的具体过程

看一段代码

public class Fu {

    public void m(Object obj){
        System.out.println("父类Object方法执行");
    }

    public static void main(String[] args){
        Fu f = new Zi();
        f.m(1);
    }

}

class Zi extends Fu{

    public void m(Object obj){
        System.out.println("子类Object方法执行");
    }

    public void m(Integer i){
        System.out.println("子类Integer方法执行");
    }
}

output:
子类Object方法执行

为啥选择子类的m(Object)方法执行,而不是m(Integer)方法执行呢,你肯定想说因为向上转型,不能执行子类特有的方法,确实是这样,但为什么呢?

  • 来看一下方法调用的过程
    编译期:
    1、编译器根据变量f声明的类型Fu,去Fu类中查找名字为m的方法。
    2、此时可能找到多个名为m的方法,因为方法是可以重载的,编译器再根据调用方法时提供的参数类型,去找到最匹配的方法,在这里是m(Object)方法,
    这个过程叫做重载解析。重载解析后,编译器获得了方法的签名(方法名+形参类型)。
    3、如果方法是被static、final、private修饰的,该方法不能被重写,f.m(1)运行时,无论f引用什么子类对象,都是执行的父类的方法,此时可以确定运行时无论f的对象是什么都是执行父类中的方法,绑定Fu类中的m(Object)方法。此为前期绑定,也叫静态绑定,是编译期时发生的绑定。
    4、如果方法不被static、final、private修饰,编译器采用动态绑定,记录方法签名m(Object)。
    运行期:
    执行f.m(1)字节码时
    1、如果是静态绑定,直接执行绑定的方法,不关心对象类型。
    2、如果是动态绑定,编译期只确定了方法签名,方法所在类未确定,根据f引用对象的实际类型,去该类型中找到签名为m(Object)的方法,执行该方法,此时运行时才把方法调用与具体方法体关联起来。

动态绑定就是运行的时候才决定执行哪个方法体,静态绑定在编译期就确定了要执行的方法体。
动态绑定在编译期确定执行的方法签名,在运行期确定执行哪个类的方法,实现自由执行子类重写的方法。静态绑定在编译期决定执行哪个类中的哪个方法,因为这些方法不能被重写,子类对象调用也是调用的父类中的,可以明确方法体,对于这类不能重写的方法,采用静态绑定性能更好,虽然采用动态绑定也能实现。

一个静态绑定的例子

public class Fu {

    private void m(){
        System.out.println("父类private方法执行");
    }

    public static void main(String[] args){
        Fu f = new Zi();
        f.m();
    }
}

public class Zi extends Fu{

    public void m(){
        System.out.println("子类public方法执行");
    }

    public static void main(String[] args){
        Fu f = new Zi();
       // f.m(); 无法编译
    }
}

output:
父类private方法执行

补充一个继承泛型类的例子

public class GenericClazz<T> {

    public void m(T t){
        System.out.println("泛型类中m()方法执行");
    }
}

public class Zi extends GenericClazz<Integer>{

    public void m(Integer i){
        System.out.println("子类中m()方法执行");
    }

//    public void m(Object i){
//        System.out.println("子类中m()方法执行");
//    } 无法编译

    public static void main(String[] args){
        GenericClazz f = new Zi();
        f.m(1);
    }
}

output:
子类中m()方法执行

泛型类中,由于有泛型擦除,T实际会被在编译时替换为Object类型,那么Zi类继承GenericClazz类就是继承的m(Object)方法,而m(Integer)是对m(Object)的重载而不是重写,在用f.m(1)调用时,按照上面的理论,运行时应该是调用的Zi类中的m(Object)方法,而m(Object)子类没有重写,应该走父类语句,但是这里却走了子类的m(Integer)方法,原因是编译器自动在子类做了m(Object)方法的重写,会执行类似下面的语句:

public void m(Object t){
    m((Integer) t);
}

让m(Integer)看起来就像是重写的父类的m(Integer)一样,并且还关闭了子类对m(Object)的手动重写,可以看到上面手动重写m(Object)编译是报错的。

标签:绑定,java,静态,子类,void,Object,方法,public
From: https://www.cnblogs.com/waczj/p/18542789

相关文章

  • Java面试之有三个线程T1,T2,T3,如何保证顺序执行?
    前言本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!有三个线程T1,T2,T3,如何保证顺序执行?似乎有点模糊了,那就大概看一下面试题吧。好记性不如烂键盘***12万字的java面试题整理***有三个线程T1,T2,T3,如何保证顺序执行?在多线程中有多种方法让线程按特定顺序执行,你可以......
  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现八
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • Java 项目注入、上传、搜索及插件挖掘的代码审计
    目录Java项目注入、上传、搜索及插件挖掘的代码审计一、什么是Java项目注入、上传、搜索及插件挖掘的代码审计二、原理(一)注入原理(二)文件上传原理(三)搜索功能安全原理(四)插件安全原理三、步骤与代码示例(一)准备工作(二)注入攻击审计步骤与代码示例(三)文件上传审计步骤与......
  • 深入理解Java的类加载与卸载机制
    在Java中,类加载和卸载是Java虚拟机(JVM)管理类生命周期的重要环节。类加载是Java动态链接机制的核心,通过它,JVM可以在运行时加载类文件。而类的卸载则是为了节省内存,将无用的类从JVM中移除。要理解类的加载和卸载,不仅有助于解决类加载异常、内存泄漏等问题,也能帮助我们更好地优......
  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现七
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • Java API笔记
    JavaAPI(ApplicationProgrammingInterface)是一组预先定义好的类和接口,帮助开发者快速开发应用程序。常用的packagejava.lang:包含了一些基础类,如Object、String、System等。java.util:提供了许多实用工具类,如集合框架(List、Set、Map)、日期/时间处理等。javafx:用于创建富客......
  • JavaScript新版本6个新功能盘点
    JavaScript在2024年更新引入了6个关键功能。从使文本和日期更易于处理,到程序等待和协同工作的新方法,甚至使模式更容易查找。我们一起来看看吧!01、格式正确的Unicode字符串格式良好的Unicode字符串引入了确保JavaScript中的字符串以UTF-16编码正确格式化的方法。此......
  • tips1:WPF绑定的一种情况 Binding
    <CheckBoxMargin="10"VerticalAlignment="Center"IsChecked="{BindingRelativeSource={RelativeSourceTemplatedparent},Path=IsExpanded}"/>CheckBox的IsChecked属性使用了数据绑定机制,以实现与TemplatedParent......
  • JAVASCRIPT 将推出新的时间、日期和集合功能
    我们预计将在ECMAScript2025中看到的重大JavaScript新功能,以及导致它们延迟的讨论。译自JavaScriptDueforNewTime,DateandSetFeaturesNextYear,作者MaryBranscombe。JavaScript下一个年度更新将在新年初确定其包含的功能,包括在2025年3月前达到最终第四阶......
  • Java流程控制(三)
    用户交互Scanner(java.util.Scanner获取用户的输入)//基本语法Scanners=newScanner(System.in)通过Scanner类的next()与nextLine()方法获取输入的字符串,使用hasNext()与hasNextLine()判断是否还有输入的数据(Next不能得到带有空格的字符串,NextLine可以获得空白)importjava......