java 多态,和方法覆盖分析(转)
多态 (Polymorphism) 大家应该都不陌生,它是我们开发面向对象系统的“老朋友”了 。但是老朋友也会有“烦心”的时候啊,呵呵。有时候 不注意,还真会被它难到。譬如下面这个例子(thank Hayden)。大家可以先不看下面的答案,在自己脑海中运行一道,看看自己想的跟实际结果是否 相符。
public static void main(String[] args) {
A b = new B();
b.fb();
}
}
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......");
}
}
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 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会很痛苦 的:)
转http://hi.baidu.com/daping_zhang/blog/item/2bba09fa10bc489759ee90bc.html
java 多态,和方法覆盖分析(转)的更多相关文章
- c#和java中的方法覆盖——virtual、override、new
多态和覆盖 多态是面向对象编程中最为重要的概念之一,而覆盖又是体现多态最重要的方面.对于像c#和java这样的面向对象编程的语言来说,实现了在编译时只检查接口是否具备,而不需关心最终的实现,即最终的实 ...
- java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?重写跟重载的区别?
java中的方法重载发生在同一个类里面两个或者多个方法的方法名相同但是参数不同的情况.与此相对,方法覆盖是说子类重新定义了父类的方法.方法覆盖必须有相同的方法名,参数列表和返回类型. 覆盖者可能不会限 ...
- Java 多态 虚方法
Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载. 看代码: package com.company; public class Main { public stati ...
- java多态/重载方法——一个疑难代码引发的讨论
直接上代码,看这个代码发现自己的基础有多差了.参考 http://www.cnblogs.com/lyp3314/archive/2013/01/26/2877205.html和http://hxra ...
- 类与接口(五)java多态、方法重写、隐藏
一.Java多态性 面向对象的三大特性:封装.继承.多态. 多态的类型,分为以下两种: 编译时多态: 指的是 方法重载.编译时多态是在编译时确定调用处选择那个重载方法,所以也叫 静态多态,算不上真正的 ...
- 【JAVA】笔记(4)---继承;方法覆盖;多态机制;super;
继承(extends): 1.作用:为方法覆盖和多态机制做准备:使代码得到复用(节省代码量): 2.格式: class 子类 extends 父类 3.理解继承:子类继承父类,其实就相当于把父类的类体 ...
- PHP面向对象编程之深入理解方法重载与方法覆盖(多态)
这篇文章主要介绍了PHP面向对象编程之深入理解方法重载与方法覆盖(多态)的相关资料,需要的朋友可以参考下: 什么是多态? 多态(Polymorphism)按字面的意思就是"多种状态" ...
- Java 方法覆盖和方法重载
方法重载(overloaded),要求方法的名称相同,参数列表不相同. 方法覆盖(override),要求①方法名相同,②参数列表相同,③返回值相同 如果是方法覆盖,要注意以下几种情况: 1.子类方法 ...
- 【Java基础 项目实例--Bank项目5】Account 和 customer 对象等 继承、多态、方法的重写
延续 Java基础 项目实例--Bank项目4 实验要求 实验题目 5: 在银行项目中创建 Account 的两个子类:SavingAccount 和 CheckingAccount 实验目的: 继承 ...
随机推荐
- MD5加密类
public class MD5Util { public static String getMD5(String s) { char hexDigits[] = {'0', '1', '2', '3 ...
- DELL R410升级网卡驱动
官方链接http://zh-cn.broadcom.com/support/ethernet_nic/netxtremeii.php(官方驱动的名字偶尔会改) 注意确保服务器的kernel-dev ...
- Windows系统创建硬链接文件
源文件夹:E:\深海 创建新硬链接文件夹:D:\微云同步盘\719179409\4-工作资料\深海 打开命令提示符(管理员) 敲入以下命令: 创建成功后,进入目录 D:\微云同步盘\71917 ...
- MySQL教程:数据库具体操作
1. 连接数据库服务器 $ ./mysql -h host_name -u user_name -p -h host_name(--host=host_name),连接的数据库主机名,如果在本地主机上 ...
- mysql UNIX时间戳与日期的相互转换
UNIX时间戳转换为日期用函数: FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 日期转换为UNIX时间戳用函数: UNIX_TIMESTAMP() ...
- Windows 7 64位下解决不能创建Django项目问题
把djingo-admin.py的全路径写出来 在cmd命令行下直接输入python C:\Python27\Scripts\django-admin.py startproject site(sit ...
- 洛谷 P1515 旅行
P1515 旅行 题目描述 你要进行一个行程为7000KM的旅行,现在沿途有些汽车旅馆,为了安全起见,每天晚上都不开车,住在汽车旅馆,你手里现在已经有一个旅馆列表,用离起点的距离来标识,如下: 0, ...
- 将Activity设置成半透明的对话框
将Activity设置成半透明的对话框 在定义Activity时指定Theme.Dialog主题就可以将Activity设置成对话框风格.通过修饰Theme.Dialog主题的android:wind ...
- 如果设置http.get超时控制
var timeout_wrapper = function (req) { return function () { // do some logging, cleaning, etc. depen ...
- 基础知识 mfc
句柄 资源的标示 图标句柄(HICON) 光标句柄(HCURSOR) 窗口句柄(HWND) 类似于指针 wm_keydown表示键盘上的按键按下了数值 WPARAM ||LPARAM 两个整形数据 ...