通过实例聊聊Java中的多态
Java中的多态允许父类指针指向子类实例。如:Father obj=new Child(); 那么不禁要发问??
使用这个父类型的指针访问类的属性或方法时,如果父类和子类都有这个名称的属性或方法,哪一个属性或方法会被调用呢?
动手看看
class Father
{
int r;
Father()
{
r=4;
}
void printname()
{
System.out.println("I'm father");
}
}
class Child extends Father
{
int r;
Child()
{
r=5;
}
void printname()
{
System.out.println("I'm Child");
}
}
public class Test
{
public static void main(String[] args)
{
Father obj=new Child();
System.out.println(obj.r);
obj.printname();
}
}
测试结果:
4
I'm Child
结果说明。属性会访问父类的。方法会访问子类的。
不要以为Father obj=new Child();这条语句一定会让obj.printname()指向Chlid定义的printname()。实际上,如果你把Father类中的printname()方法删除,这个程序将编译失败。因为Father中的并没有定义printname()这个函数。 因为在Father obj=new Child()这个语句中,如果Father中没有printname()这个函数,就不会为obj建立一个用于调用printname()函数的指针。所以调用obj.printname()会出错。如果Father中有这个函数。指向printname()函数的指针会被创建。在调用obj.printname()时,不会出错,而且,因为obj指向的是new Child(),是个Chld类的实例。所以调用obj.printname()时调用了Child类中定义的printname()。这就是方法的动态绑定。
那么,刚才说到把Father类中的printname()方法删掉后,obj将无法调用Child类中的printname(),因为obj.printname()会编译失败。那么如果我就是需要调用要怎么办呢?其实虽然obj是Father类型的,但是它指向的是一个Child类的实例。那么可以将obj强制类型转换为Child。再调用printname()方法就可以了。
在上面程序中,把Father类中的printname()方法整个删掉,再将obj.printname() 改成 ((Child)obj).printname()后,
编译成功,结果输出:
4
I'm Child
不禁要思考 如何可以运行Child类中的printname()来输出“I'm Father”呢?
我的办法 办法就是将Child类中定义的printname()整个删掉。为什么这样可以成功呢?自己想想,嘿嘿。最后会有个这样的思考题。
好了说完方法,接下来说属性
为什么obj.r是4?为什么不是5?
呵呵。其实从哲学上讲很好理解,把自己想象为多态的设计者,如果属性还是指向子类的属性(已知方法是指向子类的方法了 ),那和new一个子类有什么区别,肯定是这个引用即可以用父类的“某些东西”,也可以用子类的“某些东西”,那才有”竞争力(存在意义)”。 留一个思考:为什么不反过来(指向父类的方法,子类的属性)?
好了如下是正经解释:Java中的多态仅为方法而言,成员变量还是使用的父类的成员变量。也就是说,因为“Father obj =……”,所以obj是Father类型的,所以obj里面的r是Father里面的r,所以输出obj.r就是4了。
能不能输出5? 如下 向下转型
((Child)obj).r
那行 测试一下吧
class Base {
int i = 99;
public void amethod() {
System.out.println("Base.amethod()");
}
Base() {
amethod();
}
}
public class Derived extends Base {
int i = 1;
public static void main(String argv[]) {
Base b = new Derived();
System.out.println(b.i);
b.amethod();
}
public void amethod() {
System.out.println("Derived.amethod()");
}
}
结果:
Derived.amethod()
99
Derived.amethod()
这个程序的执行过程是这样的:
第一行:Base b=new Derived();
执行这一行语句的过程中,要构造Derived这个类,而它有父类Base,所以先构造Base类。构造Base类的默认构造函数有定义。内容是执行amethod()方法。
实际上,Base类构造方法中的执行amethod(),相当于执行this.amethod(),在这个程序中,就相当于执行b.amethod()。而b是Base类型的,指向了Derived类的实例的指针。所以跟据上面我们的总结,实际上执行的是Derived类的amethod()函数。所以,第一行“Base b=new Derived();”执行完,输出"Derived.amethod()"。
第二行:System.out.println(b.i);
这个很简单,成员变量,不考虑多不多态,只看它定义时前面的类型。这个程序中是Base b,所以b.i就是Base类中的i。输出99
第三行:b.amethod();
调用Derived类中的amethod()方法。
其实这行就是迷惑你的,如果没有这一行。你可能会警觉起来——咦?为什么这儿定义一个amethod()呢?没有地方调用它啊?
有了这行代码,就会使你放松警惕。觉得,啊。定义了这个是用来让b.amethod();调用的。
如果把Derived的amenthod删除 结果如何?
Base.amethod()
99
Base.amethod()
通过实例聊聊Java中的多态的更多相关文章
- 简单聊聊java中的final关键字
简单聊聊java中的final关键字 日常代码中,final关键字也算常用的.其主要应用在三个方面: 1)修饰类(暂时见过,但是还没用过); 2)修饰方法(见过,没写过); 3)修饰数据. 那么,我们 ...
- 深度分析:理解Java中的多态机制,一篇直接帮你掌握!
Java中的多态 1 多态是什么 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.用白话来说,就是多个对象调用同一 ...
- 13、java中的多态
1,多态的体现 父类的引用指向了自己的子类对象. 父类的引用也可以接收自己的子类对象.2,多态的前提 必须是类与类之间有关系.要么继承,要么实现. 通常还有一个前提:存在覆盖. 3,多态的好处 多态的 ...
- java中实现多态的机制是什么?
多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次 ...
- Java 中的多态,一次讲个够之接口实现关系中的多态
上文还没有写完,这一篇继续 Java 中的多态,一次讲个够之继承关系中的多态 https://www.cnblogs.com/qianjinyan/p/10824576.html 接口实现关系,和继承 ...
- Java中实现多态的条件是什么
java中实现多态需要三个条件: 1,需要有继承关系的存在. 2,需要有方法的重写. 3,需要有父类的引用指向子类对象.
- 聊聊Java中的反射(一)
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 反射reflection主要为了动态操作Java代码,它的主要功能体现在Java提供的refl ...
- 实例说明Java中的null
翻译人员: 铁锚 翻译时间: 2013年11月11日 原文链接: What exactly is null in Java? 让我们先来看下面的语句: String x = null; 1. 这个语句 ...
- 深入理解Java中的多态
一.什么是多态? 多态指同一个实体同时具有多种形式.它是面向对象程序设计(OOP)的一个重要特征.如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的. 二.多态是如何实现的? ...
随机推荐
- Vue中,过滤器的使用方法!
Vue.js允许自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和v-bind表达式.过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示:(借官方的 ...
- Mac 常用软件
command+space开启新的一天 窗口管理:Magnet 写代码:Pycharm.vscode.sublime text 虚拟机:VMware Fusion(买不起Parallels Deskt ...
- Delphi 控制程序的执行
- web攻击日志分析之新手指南
0x00 前言 现实中可能会经常出现web日志当中出现一些被攻击的迹象,比如针对你的一个站点的URL进行SQL注入测试等等,这时候需要你从日志当中分析到底是个什么情况,如果非常严重的话,可能需要调查取 ...
- 2019-2020-1 20199319《Linux内核原理与分析》第五周作业
系统调用的三层机制(上) 基础知识 1.通过库函数的方式进行系统调用,库函数用来把系统调用给封装起来. 2.CPU有四种不同的执行级别:0.1.2.3,数字越小,特权越高.Linux操作系统中采用了0 ...
- U-boot新手入门,烧写进mini2440
拿到一块开发板,首先就要找到它的资料,当然了,开发板的厂商或者代理商会提供资料,资料里会有你需要的. 比如我的这块mini2440,在友善之臂代理商提供的资料里面,就有我们这篇所需要的 把这个文件夹下 ...
- php+ajax远程加载避免重复提交
近日在练习签到送积分功能时,发现可以在一瞬间的时候提交好多次 导致可以重复领取多次积分 除了增加请求限制之外 发现ajax提交没有限制重复提交 遂立此贴为警示 首先上表单代码 <form ons ...
- 标准C语言(9)
C语言里所有文字信息必须记录在一组连续的字符类型存储区里所有文字信息必须以字符'\0'做结尾,这个字符的ASCII码就是0符合以上两个特征的内容叫字符串,它们可以用来在程序里记录文字信息.字符串里'\ ...
- [报错] Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
今天下午做python的作业,我用PyQt5 中 利用QWebEngineView打开外部网页. 但是一直闪退,一运行就闪退. 显示报错:Process finished with exit code ...
- Codeforces 708D 上下界费用流
给你一个网络流的图 图中可能会有流量不平衡和流量>容量的情况存在 每调整一单位的流量/容量 需要一个单位的花费 问最少需要多少花费使得原图调整为正确(可行)的网络流 设当前边信息为(u,v,f, ...