Java静态分派和动态分派

前言

动态分派和静态分派机制是Java多态实现的原理。本文将针对这两种机制进行浅析。

静态分派

静态分派机制最典型的代码示例如下

    void test() {
        Father father = new Son();          //静态分派
        print(father);
    }

    void print(Father father) {
        System.out.println("this is father");
    }

    void print(Son son) {
        System.out.println("this is son");
    }

这段代码执行完成以后会输出this is father。之所以会输出这样一个结果,原因就是此处的多态实现是静态分派的。在编译阶段,由于father变量类型被声明为Father。因此在编译阶段就已经确定了调用的是参数为Father的方法,与具体的实例化对象无关

动态分派

动态分派机制最典型的代码示例如下

    void test() {
        Father father = new Son();          //静态分派
        father.name();      //动态分派
    }

    class Son extends Father {
        void name(){
            System.out.println("son");
        }
    }

    class Father {
        void name(){
            System.out.println("father");
        }
    }

这里我们声明了静态类型Father,但是实际上我们调用name方法的时候,输出的却是son。这里就牵扯到一个动态分派的问题,对于方法重写,Java采用的是动态分派机制,也就是说在运行的时候才确定调用哪个方法。由于father的实际类型是Son,因此调用的就是Son的name方法。

单分派与多分派

静态分派是多分派的,动态分派是单分派的。
多分派是指在静态分派的过程中需要考虑两步:
1、判断静态类型是Father还是Son
2、判断方法参数是Father还是Son
综合上述两个因素(宗量),才能确定调用哪个方法。
而动态分派由于使用的时候已经确定了参数类型,所以不需要对参数类型进行判断,只需要对变量类型进行判断即可。比如在上述例子中,我们已经通过静态分派,确定了调用的是无参的name方法,这时候我们就只需要考虑father的实际类型是Father还是Son即可。因此动态分派是单分派的。

总结

在Java多态的两种常见用法中,方法重载使用的是静态分派机制,而方法重写使用的是静态分派机制。这也就导致了,方法重载调用的时候是根据变量的静态类型来决定调用哪个方法。而方法重写的时候,则是根据变量的实际类型来决定调用哪个方法。

转自https://www.cnblogs.com/zhenlingcn/p/8539065.html

原文地址:https://www.cnblogs.com/smilepup-hhr/p/11224960.html

时间: 2024-08-29 09:58:05

Java静态分派和动态分派的相关文章

(三十)分派调用:静态分派和动态分派

分派调用 其实分派分为两种,即动态分派和静态分派.我们在了解分派的时候,通常把它们与重写和重载结合到一起. 重载(overload)与静态分派 我们先看一个题: public class Main { static abstract class Father { } static class Son extends Father { } static class Daughter extends Father { } public void getSex(Daughter daughter) {

Java方法重载与重写(静态分派与动态分派)

Java面向对象3个基本特征:继承.封装和多态:多态主要体现在重载和重写: 1.静态分派 静态分派与重载有关,虚拟机在重载时是通过参数的静态类型,而不是运行时的实际类型作为判定依据的:静态类型在编译期是可知的: 1)基本类型 以char为例,按照char>int>long>double>float>double>Character>Serializable>Object>...(变长参数,将其视为一个数组元素) 变长参数的重载优先级最低 (注意char

Java静态分派与动态分派(二)

方法调用并不等于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程. 在程序运行时,进行方法调用是最普遍.最频繁的操作,但是Class文件的编译过程不包括传统编译中的连接步骤,一切方法调用在Class文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址(相对于之前说的直接引用).这个特性给Java带来了更强大的动态扩展能力,但也使得Java方法调用过程变得相对复杂起来,需要在类加载期间,甚至到运行期间才能确定目标方

多态性实现机制——静态分派与动态分派

方法解析 Class 文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在 Class 文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址.这个特性给 Java 带来了更强大的动态扩展能力,使得可以在类运行期间才能确定某些目标方法的直接引用,称为动态连接,也有一部分方法的符号引用在类加载阶段或第一次使用时转化为直接引用,这种转化称为静态解析.这在前面的“Java 内存区域与内存溢出”一文中有提到. 静态解析成立的前提是:方法在程序真正执行前就有一个可确定的调用版本,并

深入浅出java静态代理和动态代理

首先介绍一下,什么是代理: 代理模式,是常用的设计模式.特征是,代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类.以及事后处理消息. 代理类和委托类,存在着关联关系.代理类的对象本身并不真正实现服务,知识通过调用委托类的对象的相关方法. 代理类可以分为两种:静态代理和动态代理. 静态代理: 代理类是由程序员创建,或由工具生成的代码 编译成的.在程序运行前,代理类的 *.class文件已经存在了.直接就可以运行 . 动态代理: 动态代理的代理类.没有直接由

Java静态代理与动态代理模式的实现

前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总没有时间见面,他也没办法.后来,房东想了一个办法,他找到了一个人代替自己和小王洽谈,房东本人不用出面,他只要把他的对房客的要求告诉他找的那个人,那个人和你商量就可以了,这样就可以完成租房这件事了.这种现实场景比比皆是,所呈现出来的其实就是代理模式的原型的一种.我们把焦点转向编程,你是否在编程中经常遇见这样一个问题,对于访问某个对象,我们希望给它的方法前加入一

java静态代理与动态代理简单分析

原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理,静态代理是在编译时就将接口.实现类.代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理,动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能. 其实方法直接调用就可以完成功能,为什么

Java 静态代理和动态代理

Java 静态代理 静态代理通常用于对原有业务逻辑的扩充.比如持有二方包的某个类,并调用了其中的某些方法.然后出于某种原因,比如记录日志.打印方法执行时间,但是又不好将这些逻辑写入二方包的方法里.所以可以创建一个代理类实现和二方方法相同的方法,通过让代理类持有真实对象,然后在原代码中调用代理类方法,来达到添加我们需要业务逻辑的目的. 这其实也就是代理模式的一种实现,通过对真实对象的封装,来实现扩展性. 一个典型的代理模式通常有三个角色,这里称之为**代理三要素** 共同接口 public int

java静态代理和动态代理(一)

代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题. 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从