`
michaelqi007
  • 浏览: 7672 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Java运行时绑定探讨

阅读更多
版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://zhangjunhd.blog.51cto.com/113473/49452
本文探讨 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
调用的成员:儿子属性
分享到:
评论

相关推荐

    Java动态绑定和静态绑定.doc

    接下来,我们转向动态绑定(也称为晚期绑定或运行时绑定)。动态绑定发生在程序运行时,根据对象的实际类型来决定调用哪个方法。只有虚方法(即被`override`的方法)才支持动态绑定。例如: ```java class Animal {...

    Java动态绑定的方法重载的实现.zip

    在Java中,非静态的实例方法调用是动态绑定的,这意味着编译器并不知道具体调用哪个方法,而是在运行时根据对象的实际类型来决定。这是基于多态性的一个关键特性。多态性允许子类对象可以被视为父类对象,从而能够...

    RoboVM和libGDX的绑定[用java调用ios的静态库.a]

    本篇文章将详细探讨如何通过RoboVM与libGDX进行绑定,以利用Java调用iOS的静态库.a。 首先,RoboVM是一个开源的Java虚拟机,它允许Java和Scala代码直接在iOS设备上运行,从而打破了Java只能在Android平台上运行的...

    Java-Thread-Affinity:将Java线程绑定到给定的内核

    本主题将深入探讨Java如何实现线程亲和性,以及其背后的原理和实践应用。 首先,线程亲和性有助于减少因线程在不同核心之间迁移产生的额外开销,这种开销包括缓存失效和上下文切换。当线程长时间运行在同一个核心上...

    基于java的本地代码绑定工具 jSegue.zip

    - **动态加载**:支持动态加载本地库,允许在运行时添加或更新本地代码,提高了程序的可维护性和灵活性。 3. **使用jSegue的步骤**: - **配置环境**:确保安装了Java SDK和C/C++编译器,设置好相应的环境变量。 ...

    基于Java的实例源码-本地代码绑定工具 jSegue.zip

    "基于Java的实例源码-本地代码绑定工具 jSegue.zip" 这个标题揭示了我们要探讨的核心内容。它是一个基于Java编程语言的实例源代码,专门用于本地代码绑定。本地代码绑定通常涉及到Java应用程序与操作系统底层功能的...

    Java序列化技术的探讨.pdf

    "Java序列化技术的探讨" Java序列化技术是Java中的重要技术,在RMI、AJAX、Web Service等方面都有应用。本文将介绍几种常用的Java序列化技术,并通过比较、分析这些技术在功能、序列化后的字节数和序列化、反序列化...

    java socket 用户真实IP测试

    在标题“java socket nginx tcp转发 用户真实IP测试”中,主要探讨的是如何在Java的Socket连接中,通过Nginx的TCP转发获取到实际用户的IP地址。 在描述中提到的博客文章,很可能是详细介绍了这个问题的解决方案。...

    Java全能速查宝典

    Java运行时环境(JRE)包含了JVM以及运行Java应用程序所需的类库和其他组件。 3. **编译与运行**:Java源代码文件以.java为扩展名,通过javac命令进行编译后生成字节码文件(.class),最后通过java命令运行。 4. **基本...

    java中多态的内存分析

    多态性分为编译时多态和运行时多态,其中运行时多态是Java中最常见的形式,也称为动态绑定。在深入探讨Java中多态的内存分析之前,我们需要先理解一些基本概念。 首先,了解Java内存模型至关重要。Java程序运行时...

    android 绑定服务客户端

    本篇文章将详细探讨“Android绑定服务客户端”的相关知识点,以及如何实现客户端与服务端之间的交互。 **一、绑定服务的基本概念** 绑定服务允许其他应用组件(如Activity或BroadcastReceiver)通过Binder对象直接...

    Java开发的发票打印

    在本文中,我们将深入探讨Java如何用于开发此类应用程序,以及相关的关键知识点。 首先,让我们了解Java语言在处理打印任务时的优势。Java具有跨平台的特性,这意味着同一段代码可以在多种操作系统上运行,如...

    ubuntu下java可用的gdal库及使用示例代码

    在Eclipse中,你需要配置项目的构建路径,将GDAL的Java绑定库包含进来,以便于编译和运行代码。 在“gdal-try”这个压缩包文件中,很可能包含了编译GDAL的步骤说明、SWIG配置文件、Java接口代码示例,以及可能的...

    wsdl生成java代码工具

    - **命令行参数**:运行`wsdl2java`时,可以指定各种参数,比如指定输出目录 (`-d`)、选择代码生成模式 (`-frontend`) 或指定特定的绑定配置 (`-b`)。 - **修改路径**:根据实际项目需求,用户可能需要修改Wsdl2...

    linux版gdal3.0.0版本编译文件Java用

    这里我们将详细探讨如何在Linux系统上编译GDAL 3.0.0版本,并使其适用于Java应用。 1. **环境准备**: 在开始编译之前,确保你的Linux系统安装了以下基础工具和库: - GCC编译器 - CMake构建系统 - Java开发...

    Java转C++代码工具 J2C

    在深入探讨J2C之前,我们先理解一下Java和C++之间的主要差异以及为什么会有这样的转换需求。 Java是一种跨平台、面向对象的编程语言,它通过Java虚拟机(JVM)运行。它的设计目标是简化编程,提供自动内存管理...

    java调用chrome浏览器内核cef实现,非jxbrowser

    Java调用Chrome浏览器内核是开发桌面应用时一个常见的需求,尤其在需要嵌入Web页面或者与Web内容交互的场景下。CEF(Chromium Embedded Framework)是一个开源项目,它允许开发者将Google Chrome的Blink渲染引擎和V8...

    luajava1.1 64位版本和32位版本

    同时,注意检查lua51.dll或libluajit-5.1.so(根据操作系统不同)是否正确配置,这是luajava运行的关键。 总的来说,luajava通过提供一个桥梁,使得Java开发者可以利用Lua的强大脚本能力,实现快速开发和调试。选择...

    wsdl2java 生成wsdljava客户端所需要的包

    在压缩包`lib`中,很可能包含了生成Java客户端时所必需的一些依赖库,例如Apache CXF的运行时库、JAXB库(用于XML到Java对象的转换)以及其他可能的第三方库。确保你的项目构建系统(如Maven或Gradle)正确地把这些...

    Feign是一个Java到HTTP客户端绑定器

    - **动态代理**: 当你创建一个Feign接口的实例时,Feign会创建一个动态代理对象,这个代理对象会在运行时根据接口方法的注解生成HTTP请求。 - **请求构建**: Feign会根据注解解析出请求的URL、HTTP方法、请求头和...

Global site tag (gtag.js) - Google Analytics