理解Java多态
多态又称Polymophism,poly意思为多,polymophism即多种形态的意思。一种类型引用因为指向不同的子类,表现出不同的形态,使用不同的方法。
什么是多态
多态建议我们编码时使用common interface(公共接口)而不是concrete implementation(具体实现)。如果我们依赖具体实现来编码,则当我们需要增加common interface的新的实现时,我们需要复制和改变已有代码。程序的可扩展性大大降低。
StackOverflow上关于什么是多态的一个例子很容易记忆。
public abstract class Human{
...
public abstract void goPee();
}
/* 抽象方法goPee()对于Human没有实现,它只对男女这两个子类有具体的不同的实现。
Human也是一个抽象类,因为人只有男或女这两个类,不能创建一个既不是男也不是女的Human。 所以我们通过使用抽象类延迟了实现。*/ public class Female extends Human{
...
@Override
public void goPee(){
System.out.println("Sit Down");
}
} public class Female extends Human{
...
@Override
public void goPee(){
System.out.println("Sit Down");
}
}
//创建一组人要去尿尿
public static void main(String[] args){
ArrayList<Human> group = new ArrayList<Human>();
group.add(new Male());
group.add(new Female());
// ... add more... // tell the class to take a pee break
for (Human person : group) person.goPee();
}
运行结果:
Stand Up
Sit Down
...
Java如何实现多态
Java支持实现多态的三个必要条件:继承(inheritance),重写(override),向上转型(upcasting)
继承:
java只支持单继承,即子类和超类之间的关系是“Is-a”的关系。
重写:
父类中的方法会原封不动地被子类继承拥有,但如果子类想做一定的修改,就需要采用方法的重写。父类中的某方法如果与子类中的方法有相同的名称和参数,则该方法被重写。
如果需要在子类中使用被覆盖的父类方法,则可使用super()关键字。子类函数的访问修饰权限不能少于父类。(试想如果一个父类中的方法为public,而在子类中重写为private,则父类类型的引用变量不能调用子类实例对象的方法,导致出错。)
向上转型:
形象化理解即为超类实际上是子类的子集,因为超类的成员都是子类的成员,所以类似Animal cat = new Cat();这样的向上转型是安全的,因为父类引用变量可以操作的成员一定在子类中。与此相反的向下转型则需要使用Instanceof来判断是否安全。
动态绑定:
动态绑定又称后期绑定,是指编译器在编译期间不知道要调用哪个方法,直到运行时才能确定。方法的动态绑定是基于实例对象类型,而不是对象引用的类型。基本上实例方法都在运行时绑定,而private方法,static方法,final方法都在编译时期绑定,称为静态绑定或后期绑定。这也是为什么private, static, final方法不允许重写。
当超类对象引用变量引用子类的对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的成员方法必须在超类中定义过,也就是说被子类覆盖的方法。
总结:
以上机制允许java运行期间执行某个类的成员方法,而不是编码时期声明类型决定。(Method overriding allows java invoke method based on a perticular object at run-time instead of declared type while coding.)
例子:
public class TradingSystem{
public String getDescription(){
return "electronic trading system";
}
} public class DirectMarketAccessSystem extends TradingSystem{
public String getDescription(){
return "direct market access system";
}
} public class CommodityTradingSystem extends TradingSystem{
public String getDescription(){
return "Futures trading system";
}
}
何时使用多态:
- 使用超类作为方法参数,可以在方法内调用不同类的成员方法。
public void showDescription(TradingSystem tradingSystem){
tradingSystem.description();
} - 使用超类声明变量,可以接收Factory method的返回值。
String systemName = Configuration.getSystemName();
TradingSystem system = TradingSystemFactory.getSystem(systemName); - 使用超类作为返回值
public TradingSystem getSystem(String name){
//code to return appropriate implementation
}
这篇文章提供了一个很好的例子
对于Java实现讲解的好文章
参考文章:
What is polymorphism in Java? Method overloading or overriding?
Java 重写(Override)与重载(Overload)
理解Java多态的更多相关文章
- 深入理解java多态没有烤山药的存在,java就不香了吗?
目录 1. 从吃烤山药重新认识多态 2. 多态前提条件[重点] 3. 多态的体现 4. 多态动态绑定与静态绑定 5. 多态特性的虚方法(virtual) 7. 向上转型 8. 向下转型 9. 向上向下 ...
- 深入理解Java多态机制
从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...
- 深入理解JAVA多态原理
之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正. 多态的概念 ...
- 【转】深入理解Java多态原理
之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正. 多态的概念 ...
- 巩固java(五)----通过实例理解java多态
package duotai; class A{ public String show(){ return "A"; } } class B extends A{ public S ...
- java提高篇(四)-----理解java的三大特性之多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- java提高篇(三)-----理解java的三大特性之多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- (转)java提高篇(四)-----理解java的三大特性之多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- 关于java多态的理解
要理解多态,就必须有一个大的理解方向,不然很容易绕进去. 首先知道多态的释义:多态性是指一个名词可以有多种语义. 对于java的多态性学习者来说,就是必须要知道多个同名方法在不同情况下的使用规则. j ...
随机推荐
- Binary Numbers(HDU1390)
Binary Numbers 点我 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- Qt中如何 编写插件 加载插件 卸载插件
Qt中如何 编写插件 加载插件 卸载插件是本文要介绍的内容.Qt提供了一个类QPluginLoader来加载静态库和动态库,在Qt中,Qt把动态库和静态库都看成是一个插件,使用QPluginLoade ...
- hibernate连接时指定编码方式 hibernate中文乱码问题
<property name="connection.url">jdbc:mysql://localhost:3306/cms?useUnicode=true& ...
- UML_部署图
一.部署图简介(Deployment Diagram Introduction) 二.部署图元素(Deployment Diagram Elements) 1.结点(Node) 2.结点实例(Node ...
- redhat enterprise 6.3 x86_64 上安装VirtualBox详细教程
这个教程真难找..... 安装第一步遇到的问题就是不能使用yum安装包,这是由于redhat是收费版,所以需要更新yum源列表,具体可以参考 http://www.cnblogs.com/tina-s ...
- 【Android Training UI】创建自定义Views(Lesson 0 - 章节概览)
发表在我的独立网站http://kesenhoo.github.io/blog/2013/06/30/android-training-ui-creating-custom-views-lesson- ...
- android 自定义圆形进度条
一.通过动画实现 定义res/anim/loading.xml如下: [html] view plain copy print ? <?xml version="1.0" ...
- .NET系统架构改造的经验和教训
转自: http://robbinfan.com/blog/43/rid-off-dotnet-experience 在互联网行业,基于Unix/Linux的网站系统架构毫无疑问是当今主流的架构解决方 ...
- OpenGLES 怎样在十天内掌握线性代数 - 希望这是真的!
OpenGLES 怎样在十天内掌握线性代数 - 希望这是真的! 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- c#的数据类型、运算符
数据类型:整型:int short long byte小数:double float decimal布尔:bool字符:char 定义变量:数据类型 变量名 [= 值];变量名的命名规则:1.组成的字 ...