本文探讨
Java
运行时(动态)绑定机制。
author: ZJ 2007-11-7
运行时绑定也叫动态绑定,它是一种调用对象方法的机制。
Java
调用对象方法时,一般采用运行时绑定机制。
1
.
Java
的方法调用过程
-
编译器查看对象的声明类型和方法名(对象变量的声明类型)。通过声明类型找到方法列表。
-
编译器查看调用方法时提供的参数类型。
-
如果方法是
private
、
static
、
final
或者构造器,编译器就可以确定调用那个方法。这是静态绑定。
-
如果不是上述情况,就要使用运行时(动态)绑定。在程序运行时,采用动态绑定意味着:虚拟机将调用对象实际类型所限定的方法。
2
.运行时(动态)绑定的过程
-
虚拟机提取对象的实际类型的方法表;
-
虚拟机搜索方法签名;
-
调用方法。
注意,这里说的是对象的实际类型。即在多态的情况下,虚拟机可以找到所运行对象的真正类型。
3
.在向上转型情况下的动态绑定示例
public
class
Father {
public
void
method() {
System.
out
.println(
"
父类方法,对象类型:
"
+
this
.getClass());
}
}
|
public
class
Son
extends
Father {
public
static
void
main(String[] args) {
Father sample =
new
Son();
//
向上转型
sample.method();
}
}
|
结果
1
:
父类方法,对象类型:
class samples.Son
这个结果没有疑问,声明的是父类的引用(句柄),但准确的调用了子类的对象,调用
method
,在子类中没有该方法,所以去父类中寻找到并调用之。
现在修改子类,重写
(override)method
方法。
public
class
Son
extends
Father {
public
void
method() {
System.
out
.println(
"
子类方法,对象类型:
"
+
this
.getClass());
}
public
static
void
main(String[] args) {
Father sample =
new
Son();
//
向上转型
sample.method();
}
}
|
结果
2
:
子类方法,对象类型:
class samples.Son
这个结果也是意料之中的。调用
method
时,在子类中寻找到了该方法,所以直接调用之。
4.
静态绑定成员变量
在处理
Java
类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以“找到”子类,而对象的属性还是父类的属性。
现在再进一步变化,在父类和子类中同时定义和赋值同名的成员变量
name
,并试图输出该变量的值。
public
class
Father {
protected
String
name
=
"
父亲属性
"
;
public
void
method() {
System.
out
.println(
"
父类方法,对象类型:
"
+
this
.getClass());
}
}
|
public
class
Son
extends
Father {
protected
String
name
=
"
儿子属性
"
;
public
void
method() {
System.
out
.println(
"
子类方法,对象类型:
"
+
this
.getClass());
}
public
static
void
main(String[] args) {
Father sample =
new
Son();
//
向上转型
System.
out
.println(
"
调用的成员:
"
+sample.
name
);
}
}
|
结果
3
:
调用的成员:父亲属性
这个结果表明,子类的对象
(
由父类的引用
handle)
调用到的是父类的成员变量。所以必须明确,运行时(动态)绑定针对的范畴只是对象的方法。
现在试图调用子类的成员变量
name
,该怎么做?最简单的办法是将该成员变量封装成方法
getter
形式。
public
class
Father {
protected
String
name
=
"
父亲属性
"
;
public
String getName() {
return
name
;
}
public
void
method() {
System.
out
.println(
"
父类方法,对象类型:
"
+
this
.getClass());
}
}
|
public
class
Son
extends
Father {
protected
String
name
=
"
儿子属性
"
;
public
String getName() {
return
name
;
}
public
void
method() {
System.
out
.println(
"
子类方法,对象类型:
"
+
this
.getClass());
}
public
static
void
main(String[] args) {
Father sample =
new
Son();
//
向上转型
System.
out
.println(
"
调用的成员:
"
+sample.getName());
}
}
|
结果
4
:
调用的成员:儿子属性
分享到:
相关推荐
接下来,我们转向动态绑定(也称为晚期绑定或运行时绑定)。动态绑定发生在程序运行时,根据对象的实际类型来决定调用哪个方法。只有虚方法(即被`override`的方法)才支持动态绑定。例如: ```java class Animal {...
在Java中,非静态的实例方法调用是动态绑定的,这意味着编译器并不知道具体调用哪个方法,而是在运行时根据对象的实际类型来决定。这是基于多态性的一个关键特性。多态性允许子类对象可以被视为父类对象,从而能够...
本篇文章将详细探讨如何通过RoboVM与libGDX进行绑定,以利用Java调用iOS的静态库.a。 首先,RoboVM是一个开源的Java虚拟机,它允许Java和Scala代码直接在iOS设备上运行,从而打破了Java只能在Android平台上运行的...
本主题将深入探讨Java如何实现线程亲和性,以及其背后的原理和实践应用。 首先,线程亲和性有助于减少因线程在不同核心之间迁移产生的额外开销,这种开销包括缓存失效和上下文切换。当线程长时间运行在同一个核心上...
- **动态加载**:支持动态加载本地库,允许在运行时添加或更新本地代码,提高了程序的可维护性和灵活性。 3. **使用jSegue的步骤**: - **配置环境**:确保安装了Java SDK和C/C++编译器,设置好相应的环境变量。 ...
"基于Java的实例源码-本地代码绑定工具 jSegue.zip" 这个标题揭示了我们要探讨的核心内容。它是一个基于Java编程语言的实例源代码,专门用于本地代码绑定。本地代码绑定通常涉及到Java应用程序与操作系统底层功能的...
"Java序列化技术的探讨" Java序列化技术是Java中的重要技术,在RMI、AJAX、Web Service等方面都有应用。本文将介绍几种常用的Java序列化技术,并通过比较、分析这些技术在功能、序列化后的字节数和序列化、反序列化...
在标题“java socket nginx tcp转发 用户真实IP测试”中,主要探讨的是如何在Java的Socket连接中,通过Nginx的TCP转发获取到实际用户的IP地址。 在描述中提到的博客文章,很可能是详细介绍了这个问题的解决方案。...
Java运行时环境(JRE)包含了JVM以及运行Java应用程序所需的类库和其他组件。 3. **编译与运行**:Java源代码文件以.java为扩展名,通过javac命令进行编译后生成字节码文件(.class),最后通过java命令运行。 4. **基本...
多态性分为编译时多态和运行时多态,其中运行时多态是Java中最常见的形式,也称为动态绑定。在深入探讨Java中多态的内存分析之前,我们需要先理解一些基本概念。 首先,了解Java内存模型至关重要。Java程序运行时...
本篇文章将详细探讨“Android绑定服务客户端”的相关知识点,以及如何实现客户端与服务端之间的交互。 **一、绑定服务的基本概念** 绑定服务允许其他应用组件(如Activity或BroadcastReceiver)通过Binder对象直接...
在本文中,我们将深入探讨Java如何用于开发此类应用程序,以及相关的关键知识点。 首先,让我们了解Java语言在处理打印任务时的优势。Java具有跨平台的特性,这意味着同一段代码可以在多种操作系统上运行,如...
在Eclipse中,你需要配置项目的构建路径,将GDAL的Java绑定库包含进来,以便于编译和运行代码。 在“gdal-try”这个压缩包文件中,很可能包含了编译GDAL的步骤说明、SWIG配置文件、Java接口代码示例,以及可能的...
- **命令行参数**:运行`wsdl2java`时,可以指定各种参数,比如指定输出目录 (`-d`)、选择代码生成模式 (`-frontend`) 或指定特定的绑定配置 (`-b`)。 - **修改路径**:根据实际项目需求,用户可能需要修改Wsdl2...
这里我们将详细探讨如何在Linux系统上编译GDAL 3.0.0版本,并使其适用于Java应用。 1. **环境准备**: 在开始编译之前,确保你的Linux系统安装了以下基础工具和库: - GCC编译器 - CMake构建系统 - Java开发...
在深入探讨J2C之前,我们先理解一下Java和C++之间的主要差异以及为什么会有这样的转换需求。 Java是一种跨平台、面向对象的编程语言,它通过Java虚拟机(JVM)运行。它的设计目标是简化编程,提供自动内存管理...
Java调用Chrome浏览器内核是开发桌面应用时一个常见的需求,尤其在需要嵌入Web页面或者与Web内容交互的场景下。CEF(Chromium Embedded Framework)是一个开源项目,它允许开发者将Google Chrome的Blink渲染引擎和V8...
同时,注意检查lua51.dll或libluajit-5.1.so(根据操作系统不同)是否正确配置,这是luajava运行的关键。 总的来说,luajava通过提供一个桥梁,使得Java开发者可以利用Lua的强大脚本能力,实现快速开发和调试。选择...
在压缩包`lib`中,很可能包含了生成Java客户端时所必需的一些依赖库,例如Apache CXF的运行时库、JAXB库(用于XML到Java对象的转换)以及其他可能的第三方库。确保你的项目构建系统(如Maven或Gradle)正确地把这些...
- **动态代理**: 当你创建一个Feign接口的实例时,Feign会创建一个动态代理对象,这个代理对象会在运行时根据接口方法的注解生成HTTP请求。 - **请求构建**: Feign会根据注解解析出请求的URL、HTTP方法、请求头和...