java多态的概念_java中多态概念、实现原理详解
一.什么是多态?
1.多态的定义
指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)
2.多态的作用
消除类型之间的耦合关系
3.多态的说明
近代网络小说泛滥,我们可以用它来举一个例子
某日你看见你手机上有多部小说同时更新了,比如有大主宰,雪鹰领主,龙王传说…在这里我们可以描述成如下:
小说a=大主宰
小说b=雪鹰领主
小说c=龙王传说
…
这里所表现的就是多态,大主宰,雪鹰领主,龙王传说都是小说的子类,我们仅仅可以通过小说这个父类就能够引用不同的子类,这就是多态–我们只有在运行的时候才会知道引用变量所指向的具体实例对象
当然,这样的理解是是远远不够的,要对多态的理解入门就必须要明白是”向上转型”
在上面的例子中,小说(XS)是父类,大主宰(DZZ),雪鹰领主(XYLZ),龙王传说(LWCS)都是其子类 于是,我们定义如下代码
DZZ a=new DZZ();
对于这段代码应该都不会感觉到陌生,无非就是实例化了一个大主宰的对象 那么对于如下的这段代码呢?
XS a=new DZZ();
在这里我们这样理解,这里定义了一个XS类型的a,让它指向了DZZ对象实例。由于DZZ是继承于XS,所以DZZ可以自动向上转型为XS,所以a可以指向DZZ实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能
但是向上转型也存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的运用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了
public class XS {
public void fun1() {
System.out.println("XS中的fun1");
fun2();
}
public void fun2() {
System.out.println("XS中的fun2");
}
}
public class DZZ extends XS{
/*
* 子类重载父类方法
* 父类中不存在该方法,向上转型后,父类是不能引用该方法的
*/
public void fun1(String a) {
System.out.println("DZZ中的fun1");
fun2();
}
/*
* 子类重写父类方法
* 调用必定使用这个方法
*/
public void fun2() {
System.out.println("DZZ中的fun2");
}
}
public class DuoTaiTest {
public static void main(String[] args) {
XS a=new DZZ();
a.fun1();
}
}
output:
XS中的fun1
DZZ中的fun2
所以对于多态我们可以总结如下:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接,动态调用)
对于面向对象,多态分为编译时多态和运行时多态,其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
二.多态的实现
1.实现条件
在刚刚开始就剃刀了继承在为多态的实现做了准备。子类Child继承父类Father,我们可以编写一个指向子类的父类类型引用,该引用既可以处理父类Father对象,也可以处理子类Child对象,当相同的消息发送给子类或者父类对象时,该对象就会根据自己所属的引用而执行不同的行为,这就是多态。即多态性就是相同的消息使得不同的类做出不同的响应
Java实现多态有三个必要条件:继承,重写,向上转型
继承:在多态中必须存在有继承关系的子类和父类
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法
只有满足了上述三个条件,我们才能够在同一个继承结构中使用同一的逻辑实现代码处理不同的对象,从而达到执行不同的行为
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法
2.实现形式
继承
public class XS {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public XS() {
}
public String drink() {
return "你看的小说名字:"+getName();
}
public String toString() {
return null;
}
}
public class DZZ extends XS{
public DZZ() {
setName("DZZ");
}
public String drink() {
return "你看的小说名字:"+getName();
}
public String toString() {
return "小说名:"+getName();
}
}
public class XYLZ extends XS{
/**
*
*/
public XYLZ() {
setName("XYLZ");
}
public String drink() {
return "你看的小说名字:"+getName();
}
public String toString() {
return "小说名:"+getName();
}
}
public class DuoTaiTest {
public static void main(String[] args) {
XS [] xs=new XS[2];
DZZ a=new DZZ();
XYLZ b=new XYLZ();
xs[0]=a;
xs[1]=b;
for(int i=0;i<2;i++) {
System.out.println(xs[i].toString()+"::::"+xs[i].drink());
}
System.out.println("-------------------");
}
}
ouput:
小说名:DZZ::::你看的小说名字:DZZ
小说名:XYLZ::::你看的小说名字:XYLZ
-------------------
在上面的代码中DZZ,XYLZ继承XS 并且重写了drink(),toString()方法,程序运行结果是调用子类中方法,输出DZZ,XYLZ的名称,这就是多态的表现。不同的对象可以执行相同的行为,但是他们都需要通过自己的实现方式来执行,这就要得益于向上转型了
我们都知道所有的类都继承自超类Object,toString()方法也是Object中方法,当我们这样写时:
Object o = new DZZ();
System.out.println(o.toString());
output:
小说名:DZZ
Object,XS,DZZ三者继承链关系是:DZZ—>XS—>Object。所以我们可以这样说:当子类重写父类的方法被调用时,只有对象继承链中的最末端的方法才会被调用。但是注意如果这样写:
Object o = new xs();
System.out.println(o.toString());
output:
null//因为DZZ并不存在于该对象继承链中
所以基于继承实现的多态可以总结如下:对于引用子类的父类类型,在处理该引用时,它适用于继承该父类的所有子类,子类对象的不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。
如果父类是抽象类,那么子类必须要实现父类中所有的抽象方法,这样该父类所有的子类一定存在统一的对外接口,但其内部的具体实现可以各异。这样我们就可以使用顶层类提供的统一接口来处理该层次的方法。
本篇文章的内容希望能给需要的朋友一些帮助
java多态的概念_java中多态概念、实现原理详解相关推荐
- java 队列已满_JAVA中常见的阻塞队列详解
在之前的线程池的介绍中我们看到了很多阻塞队列,这篇文章我们主要来说说阻塞队列的事. 阻塞队列也就是 BlockingQueue ,这个类是一个接 口,同时继承了 Queue 接口,这两个接口都是在JD ...
- java的日期操作_java中对时间的操作详解
代码演示: //数据库中去的日期 Date s = list.get(0).getSdate(); System.out.println(s);// Tue Apr 28 00:00:00 CST 2 ...
- WEB后台--邮件和短信业务实现(包括Java一键实现、封装和异步)以及原理详解
本来就打算针对一些固定的特别点的业务(QQ与网易邮件.拦截设计.短信.定时器等等)来进行记录以及解析原理,这些会比较零散记录在JavaWeb的分类里面,感兴趣的童鞋可以去看下. 有人问为什么要邮件短信 ...
- jQuery中getJSON跨域原理详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...
- java中迭代器要导包吗_java 中迭代器的使用方法详解
java 中迭代器的使用方法详解 前言: 迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式.迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节:②把元 ...
- java mod %区别_Java中 % 与Math.floorMod() 区别详解
%为取余(rem),Math.floorMod()为取模(mod) 取余取模有什么区别呢? 对于整型数a,b来说,取模运算或者取余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余 ...
- java 静态 编译_Java中的动态和静态编译实例详解
Java中的动态和静态编译实例详解 首先,我们来说说动态和静态编译的问题. Q: java和javascript有什么区别? 总结了一下:有以下几点吧: 1.首先从运行环境来说java代码是在JVM上 ...
- java中math的方法_Java中Math类常用方法代码详解
近期用到四舍五入想到以前整理了一点,就顺便重新整理好经常见到的一些四舍五入,后续遇到常用也会直接在这篇文章更新... public class Demo{ public static void mai ...
- java foreach标签_Java中Velocity foreach循环标签详解
Java中Velocity foreach循环标签详解 Java Velocity中foreach循环可以很容易的遍历数组或者集合. 定义 #foreach( $elem in $allElems) ...
- future java 原理_Java线程池FutureTask实现原理详解
前言 线程池可以并发执行多个任务,有些时候,我们可能想要跟踪任务的执行结果,甚至在一定时间内,如果任务没有执行完成,我们可能还想要取消任务的执行,为了支持这一特性,ThreadPoolExecutor ...
最新文章
- python给列表中的字典按照字典中的某个键值进行排序
- 用c语言大一个三角形图形,c语言图形,请高手修改,效果是一个三角形绕一点旋转一周...
- java.util.regex.PatternSyntaxException: Unexpected internal error near index 1 \ ^
- 【数据挖掘笔记一】引论
- 2021-06-11 pytorch基本语法
- VMware虚拟机Bridged(桥接模式)
- Allegro导出STP文件
- 面试65个问题教你怎么机智回答面试官及回答技巧
- github加速方法
- C语言 哲学家就餐问题
- 第一次参加公司研发部门高级别会议之感
- Android studio 手机扫描二维码功能
- iOS10.3正式版发布:iOS10.3新功能有哪些? 韩俊强的博客
- 执著如泪,是滴入心中的破碎
- Adguard,一键屏蔽电脑所有广告
- Element Table 单元格中嵌套表格(Table) 合并行效果
- nmap 扫描局域网内的机器 扫描指定电脑的开放的端口
- 移动端区分安卓系统和ios系统
- 生成短的8位UUID(C#+JAVA)
- win7系统不显示北京时间
热门文章
- java 微信小程序的校园跑腿系统springboot
- [转]负序电流对发电机的危害,发电机负序保护的作用
- 【visum工作笔记】之六
- 实拍互联网公司总部大楼
- 不起眼的地推行业,有人在默默搞大钱
- 随想:关于广告拦截器
- 关于广告拦截器带来的坑 - “Failed to load resource: net::ERR_BLOCKED_BY_CLIENT”
- 安卓凯立德4.2不能运行的解决方法
- 请把学生名与考试分数录入到Map中,并按分数显示前三名成绩学员的名字
- 今天比较烦,比较烦,比较烦,比较烦,比较烦......