首页 > 编程语言 >理解 Java 方法调用

理解 Java 方法调用

时间:2023-08-13 12:24:55浏览次数:43  
标签:调用 Java 虚拟机 编译器 理解 参数 类型 方法

总结自:《Java 核心技术第 10 版(套装共 2 册)-凯 S.霍斯特曼 霍斯特曼 科内尔》

下面假设要调用 x.f(args),隐式参数 x[1] 声明为类 C 的一个引用。下面是调用过程的详细描述:

1)编译器查看对象的声明类型和方法名。假设调用 x.f(param),且隐式参数 x 声明为 C 类的对象。需要注意的是:有可能存在多个名字为 f,但参数类型不一样的方法。例如,可能存在方法 f(int) 和方法 f(String)。编译器将会一一列举所有 C 类[2] 中名为 f 的方法和其超类中名为 f 的可访问到的方法[3](超类的私有方法不可访问)。

至此,编译器已获得所有可能被调用的候选方法。

2)接下来,编译器将查看调用方法时提供的参数类型。如果在所有名为 f 的方法中存在一个与提供的参数类型完全匹配,就选择这个方法。这个过程被称为重载解析(overloading resolution)。例如,对于调用 x.f("Hello") 来说,编译器将会挑选 f(String),而不是 f(int)。由于允许类型转换(int 可以转换成 double,Manager 可以转换成 Employee,等等),所以这个过程可能很复杂。如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,就会报告一个错误。[4]

至此,编译器已获得需要调用的方法名字和参数类型。

3)如果是 private 方法、static 方法、final 方法或者构造器,那么编译器将可以准确地知道应该调用哪个方法[5],我们将这种调用方式称为静态绑定(static binding)。与此对应的是,调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定

4)当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与 x 所引用对象的实际类型最合适的那个类的方法。假设 x 的实际类型是 D,它是 C 类的子类。如果 D 类定义了方法 f(String),就直接调用它;否则,将在 D 类的超类中寻找 f(String),以此类推。

每次调用方法都要进行搜索,时间开销相当大。因此,虚拟机预先为每个类创建了一个方法表(method table)[6],其中列出了所有方法的签名和实际调用的方法。这样一来,在真正调用方法的时候,虚拟机仅查找这个表就行了。在前面的例子中,虚拟机搜索 D 类的方法表,以便寻找与调用 f(Sting) 相匹配的方法。这个方法既有可能是 D.f(String),也有可能是 X.f(String),这里的 X 是 D 的超类。注意,如果调用 super.f(param),编译器将对隐式参数超类的方法表进行搜索。

比如 Employee 和 Manager 类:

虚拟机为 Employee 和 Manager 两个类生成方法表:

将 e 声明为 Employee 类型。在运行时,由于 getSalary 不是 private 方法、static 方法或 final 方法,所以将采用动态绑定。调用 e.getSalary()的解析过程为:

1)首先,虚拟机提取 e 的实际类型的方法表。既可能是 Employee、Manager 的方法表,也可能是 Employee 类的其他子类的方法表。

2)接下来,虚拟机搜索定义 getSalary 签名的类。此时,虚拟机已经知道应该调用哪个方法。

3)最后,虚拟机调用方法。


  1. 在面向对象编程中,x 通常不视为参数,但如果把 f 看作函数,那么 x 及 args 都是这个函数的参数,作为区分,把 x 称为隐式参数,args 称为显式参数。 ↩︎

  2. 注意是列举 C 类中的 f 方法而不是列出实际对象中的所有 f 方法,因为对于类型为 C 类的引用,无法调用 C 类子类中新建的方法。 ↩︎

  3. The compiler enumerates all methods called f in the class C and all accessible methods called f in the superclasses of C. ↩︎

  4. 另见 Java 方法重载中的参数匹配原则 ↩︎

  5. 因为这些方法都不会被覆盖。注意,如果在父类和子类中声明了相同方法签名的静态方法,将会按隐式参数的声明类型调用对应的静态方法(如果使用父类的类型来调用静态方法,那么将调用父类中的静态方法,另一方面如果使用子类的类型来调用静态方法,则会调用来自子类的方法)。[7] ↩︎

  6. 编译后保存在 class 文件中,加载后相关信息进入方法区,以便虚拟机在运行时执行方法 ↩︎

  7. Java 类中可以覆盖静态方法吗? ↩︎

标签:调用,Java,虚拟机,编译器,理解,参数,类型,方法
From: https://www.cnblogs.com/Higurashi-kagome/p/17626281.html

相关文章

  • java.lang.NoSuchMethodError: com.baomidou.mybatisplus.core.toolkit.StringUtils.i
    1、原因这是由于两个版本不一致导致的;<!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version&......
  • 【Quarkus技术系列】「云原生架构体系」在云原生时代下的Java“拯救者”是Quarkus,那云
    推荐超值课程:点击获取云原生时代下的Java"拯救者"在云原生时代,其实Java程序是有很大的劣势的,以最流行的springboot/springcloud微服务框架为例,启动一个已经优化好,很多bean需要lazyload的application至少需要3-4秒时间,内存需要几百M,业务逻辑稍微复杂一点点,没有1G以上的内存是......
  • Java| jdk的src源码目录讲解
    JavaJDK的源代码目录(src)包含了Java核心类库的源代码,它提供了Java编程语言的基本功能和类。src目录结构通常按照包的层次结构组织,每个包对应一个文件夹,而每个类则在相应的包文件夹中以.java文件的形式存在。目录结构-com--sun-java--applet--awt--beans--io--lang--mat......
  • Java | JDK、JRE、JVM的关系
    一、什么是JDK、JRE、JVM?JDK(JavaDevelopmentKitJava开发工具包)是提供给Java开发人员使用的,其中包含了java的开发工具集,也包括了java的运行环境JRE。它是开发者在进行Java应用程序开发时所需的完整套件。JRE(JavaRuntimeEnvironmentJava运行环境)包括java虚拟机和Java程......
  • Linux下C语言调用libcurl库获取天气预报信息
    一、概述当前文章介绍如何在Linux(Ubuntu)下使用C语言调用libcurl库获取天气预报的方法。通过HTTPGET请求访问百度天气API,并解析返回的JSON数据,可以获取指定城市未来7天的天气预报信息。二、设计思路【1】使用libcurl库进行HTTPGET请求在代码中包含<curl/curl.h>头文件,以便使用libc......
  • 深入理解JavaScript正则表达式:释放其强大力量
    深入理解JavaScript正则表达式:释放其强大力量正则表达式是一种强大的工具,用于在字符串中搜索、匹配和替换特定的模式。在JavaScript中,正则表达式是一种内置的功能,可以帮助开发人员处理各种字符串操作。本文将深入探讨JavaScript正则表达式的原理、语法和应用场景,帮助读者充分理解......
  • Java学习笔记(九)
    6.4根父类1、如何理解根父类是object这句话?(1)所有类都直接或间接的继承Object(字面解释)(2)Object类型的变量,可以接收任意类型的对象(3)Object类型的数组,可以任意类型的元素(4)规定Object[]类型的数组,可以接收任意的对象数组(5)规定Object[]类型的数组,不可以接收元素是基本数据类型的一维......
  • Java | JDK安装目录介绍
    JDK是SUN提供的一套Java开发环境,全称JavaDevelopmentKit,简称JDK,它是整个Java的核心,其中包括Java编译器、Java运行工具、Java文档生成工具、Java打包工具等。在JDK安装完毕后,会在硬盘上生成一个目录,该目录被称为JDK的安装目录,如图所示。为了更好地学习JDK,初学者需要对JDK安装目......
  • C#多线程环境下调用 HttpWebRequest 并发连接限制
    .net的HttpWebRequest或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如windowsxp,windows7下默认是2,在服务器操作系统上默认为10.如果不修改这个并发连接限制,那么客户端同时可以建立的http连接数就只有2个或10个。对于一些诸如浏览器或网络......
  • 【谷粒学院】Maven导入aliyun-java-vod-upload包依赖失败
    【谷粒学院】Maven导入aliyun-java-vod-upload包依赖失败<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-vod-upload</artifactId><version>${aliyun-java-vod-upload.version}</version></dependency&......