多态 (Polymorphism) 大家应该都不陌生,它是我们开发面向对象系统的“老朋友”了 。但是老朋友也会有“烦心”的时候啊,呵呵。有时候不注意,还真会被它难到。譬如下面这个例子,大家可以先不看下面的答案,在自己脑海中运行一道,看看自己想的跟实际结果是否相符。
java 代码
- public class Polymorphism{
- public static void main(String[] args) {
- A b = new B();
- b.fb();
- }
- }
-
- class A {
- public A(){
- }
- public void fa() {
- System.out.println("CLASS A :Function fa Runing......");
- }
-
- public void fb() {
- System.out.println("CLASS A :Function fb Runing......");
- fa();
- System.out.println("CLASS A :Function fb Stop......");
- }
- }
-
- class B extends A {
- public B(){
- }
- public void fa() {
- System.out.println("CLASS B :Function fa Runing......");
- }
-
- public void fb() {
- System.out.println("CLASS B :Function fb Runing......");
- super.fb();
- System.out.println("CLASS B :Function fb Stop......");
- }
- }
下面是它的运行结果:
CLASS B :Function fb Runing......
CLASS A :Function fb Runing......
CLASS B :Function fa Runing......
CLASS A :Function fb Stop......
CLASS B :Function fb Stop......
怎么样,猜对结果了吗?如果结果跟你想象的一模一样,那么恭喜你,你对多态已经有初步了解了,起码在语法层次上是比较熟悉了。但是,千万不要“洋洋得意”,你可否解析结果为什么会是这样吗?我们可以先来梳理一下程序流程:
1、运行main函数,创建B对象,调用B的方法fb,于是打印出"CLASS B :Function fb Runing......",都在情理之中。
2、执行super.fb(),调用父类A的方法fb,首先打印出"CLASS A :Function fb Runing......",预料之中
3、执行方法fa(),打印出"CLASS B :Function fa Runing......",呃?奇怪了,为什么不是执行A的方法fa(),而是子类B中的fa()呢?当前被执行的是类A的方法,那么虚拟机找到的应该是A类的Method Table,找到的应该是A类的方法fa()啊?难解~
4、打印"CLASS A :Function fb Stop......",返回
5、打印"CLASS A :Function fb Stop.....",返回,程序结束。
现在问题清楚了,就是虚拟机在执行类A方法的时候查找的Method Table竟然是子类B的。为什么呢?其实,只要我们清楚java方法调用的方式,这个问题就迎刃而解了。在Java虚拟机中,每启动一个新的线程,虚拟机都会为它分配一个Java栈,而每当线程调用一个java方法时,虚拟机就会在该线程的java栈中压入一个新帧,用以存储参数,局部变量等数据。我们将这个正在被执行的方法称为该线程的当前方法,其相应的栈帧为当前帧。
好了,当我们调用一个方法时,我们需要往当前帧中压入哪些参数呢?简单,方法的参数列表中不是都说得清清楚楚的吗?嗯,对于C语言来说,这个说法是正确的,但是对于诸如C++,Java,Python等面向对象语言来说,却是不对的。大家还记得那个"this"指针吗?!不错,在Java中,所有的实例方法(Instance Method)调用的时候都会把当前对象压入当前帧中,Java虚拟机正是通过这个参数来决定当前所使用的类(通过判断该对象的类型)。
在上面的例子中,main中调用b.fb()时,压入的当前对象自然是B类对象,我们记为b。在B的fb()中调用super.fb()时,压入的就是刚刚压入的对象,也就是b了。同样,在A的fb中调用fa()时,压入的也是b。因此,在使用 invokevirtual指令调用fa()时,找的就是B的方法表(当前对象b的类型为B),也就执行了类B的fa了。
这种现象在构造函数中特别常见,因为构造函数中会隐含使用调用父类的构造函数的,如果在父类的构造函数中调用了实例方法(如 A的fa),而在子类中又覆盖了这个实例方法(如 B的fa),那么得到的结果往往不是我们所要的。因此,我们最好不要在构造函数中使用多态方法,不然,Debug会很痛苦的:)
分享到:
- 2006-12-11 11:27
- 浏览 2505
- 评论(0)
- 论坛回复 / 浏览 (0 / 3722)
- 查看更多
相关推荐
多态在构造方法中的体现较少,但重要的是理解,尽管构造方法不能被重写,它们可以被子类覆盖以初始化特定状态,从而支持更复杂的构造逻辑。 #### 六、利用继承设计:纯粹继承与扩展 继承不仅是代码重用的一种手段...
Java 多态是 Java 编程语言中的一种基本概念,它允许开发者定义一个接口,并且可以通过不同的类来实现该接口。多态性是 Java 面向对象编程的核心机制之一,它使得程序更加灵活、可维护和可扩展。 多态的体现 多态...
### C++和Java多态的区别 #### 一、概述 多态是面向对象编程语言中的一个核心特性,它允许程序员能够使用基类的指针或引用指向派生类的对象,并在运行时根据对象的实际类型来选择合适的方法进行调用。这一特性增强...
Java多态是面向对象编程中的一个核心特性,它允许我们以一种统一的方式处理不同类型的对象。在Java中,多态性主要通过继承、接口和方法重写(Override)来实现。这里我们将深入探讨从虚拟机(JVM)的角度来看,Java...
6. ** finalize 方法**:虽然不是直接与多态相关的,但值得注意的是,Java中每个对象都有一个finalize()方法,这是垃圾收集器在回收对象前调用的,子类可以重写这个方法进行资源清理,但这并不保证一定会被调用,...
Java多态是面向对象编程中的一个核心概念,它允许我们使用父类的引用指向子类的对象,从而实现更灵活的代码编写。在这个“java多态实验”中,我们可以看到一系列小代码实例,这些实例旨在帮助理解和应用多态特性。...
Java多态是面向对象编程中的一个核心概念,它允许我们以一种统一的方式处理不同类型的对象。在Java中,多态性主要体现在方法的重写(Override)和重载(Overload)。通过多态,我们可以编写出更加灵活、可扩展的代码...
方法的重写 Overriding 是父类与子类之间多态性的一种表现,子类中的方法可以覆盖父类中的方法。例如,在我们的示例中,B 类中的 show 方法覆盖了 A 类中的 show 方法。 方法的重载 Overloading 是一个类中多态性的...
Java语言中的覆盖(Override)和重载(Overload)以及多态(Polymorphism)是面向对象编程的重要概念,它们是实现代码复用和灵活性的关键。 **多态性(Polymorphism)** 多态性是Java中一种允许一个接口有多种实现的方式。...
本文将详细介绍Java中的多态机制,包括重写、重载、子类与父类的继承以及Java多态的应用等方面。 #### 二、多态的定义与重要性 多态性来源于希腊语“polymorphism”,意指“多种形式”。在面向对象编程中,多态是...
Java中的多态是面向对象编程的关键特性之一,它允许一个接口或者抽象方法被多个不同的类实现,从而使得代码更加灵活且可扩展。多态的概念基于一个接口可以有多种不同的实现方式,增强了程序的多样性和适应性。 在...
本PPT教案主要讲解了Java中的继承和多态机制,包括继承、里式代换原则、多态和动态绑定、方法重载、重载构造函数和方法覆盖等概念。 继承是面向对象编程的基本机制之一,允许一个类继承另一个类的成员变量和方法。...
而运行时多态体现在方法覆盖中,具体表现为:当对象引用指向子类实例时,在编译时无法确定具体调用哪个方法,但在运行时会根据实际对象类型决定。 8. 多态的优点 多态提高了代码的可读性和可维护性,实现了代码的...
在Java中,只有标记为`@Override`的方法才被认为是重写,这样可以避免因命名冲突而错误地覆盖其他方法。 在这个实例中,所有创建的类都将实现两个接口,这将展示如何通过接口实现多态性。同时,为了进一步展示Java...
Java多态是面向对象编程中的一个核心概念,它在Java编程中扮演着至关重要的角色。在Java中,多态性(Polymorphism)允许我们使用一个接口来引用不同类型的对象,使得代码更具通用性和可扩展性。这允许我们编写出更加...
本文旨在解决Java多态调用唯一性确定问题,通过使用Soot开源工具和Java的反射机制,分析Java程序多态调用关系,确定函数调用路径,指导测试人员设计出高效、覆盖率高的测试用例。 Java多态性是面向对象语言中一个...
在Java中,多态性(Polymorphism)主要体现在两个方面:方法的重写(Overriding)和接口的实现(Interface Implementation)。这一概念是基于继承和抽象类或者接口的,使得一个接口或类可以表现出多种形态。 ### 一...
3. 方法的重写(Override)与重载(Overload):重写是指子类继承父类后,可以覆盖父类中已有的同名方法,实现不同功能。重载则是在同一类中创建多个方法,它们名字相同但参数列表不同,实现多态的一种方式。 4. ...
本文介绍了Java多态在实际应用中的体现,通过一个示例程序展示了如何使用抽象类、继承和接口等特性实现多态。 首先,文档中定义了一个抽象类Shape,这个类是所有形状类的基类,它提供了一个抽象方法area(),用于...