Java基础教程——多态
直观地说,多态就是“一个对象,多种形态 ”。比如观世音菩萨就有多种形态——

每个人都有多种形态——

具体地讲,多态是指“同一个对象、同一个方法(函数),表现出不同的行为”。
在代码层面表现为:父类对象指向子类实例;父类对象 调用(多种)子类方法。比如:
List lst; // lst以List的形式定义
lst = new ArrayList();// 实例化的时候却是子类对象
lst = new LinkedList(); // 可以是不同的子类对象
底层技术:后期绑定(动态绑定/运行时绑定),根据运行时期对象实例来动态判断要调用的方法。
示例:开车

一般考驾照是C1驾照,可以开多种小型汽车:

现定义一个汽车类,两个子类分别是“小货车”、“三蹦子”。
主类“驾照”类中编写main方法,可以分别创建两种子类的车对象,并分别调用其"驾驶()"方法。代码如下——
public class 驾照 {
public static void main(String[] args) {
小货车 b = new 小货车();
b.行驶();
三蹦子 c = new 三蹦子();
c.行驶();
}
}
class 汽车 {
public void 行驶() {
System.out.println("启动理论");
}
}
class 小货车 extends 汽车 {
public void 行驶() {
System.out.println("小货车");
}
}
class 三蹦子 extends 汽车 {
public void 行驶() {
System.out.println("三蹦子");
}
}
上例中定义了两个对象,分别是b和c,可以理解为开小货车需要先了解小货车,开三蹦子需要先了解三蹦子,有点麻烦。
能不能一照到手,随便开车?
public static void main(String[] args) {
// 小货车 b = new 小货车();
// b.行驶();
// 三蹦子 c = new 三蹦子();
// c.行驶();
汽车 c;
c = new 小货车();
c.行驶();
c = new 三蹦子();
c.行驶();
}
修改后的代码只声明了一个对象c,属于父类的实例对象,可以分别实例化为子类,虽然方法调用都是“c.行驶()”,但输出的结果是不同的。这就是多态。
向上转型,向下转型
以父类的名义实例化一个子类对象,属于向上转型。
向上转型,是自动提升的。因为上层更抽象,范围更大,没什么问题;
小货车也是车,用更抽象的上层代表下层没有问题。
但是如果说车是小货车,就不一定对了,这个属于向下转型。
向下转型,需要强制转换。因为下层更具体,可能有父类未定义的方法,转型不一定安全。
下面的代码演示了使用括号进行强制的向下转型——
public class 多态转型 {
public static void main(String[] args) {
Animal _animal = null;
Cat _cat = new Cat();
_animal = _cat;// 向上转型(自动提升):猫是动物,没问题
_cat = (Cat) _animal;// 向下转型(强制转换):动物未必都是猫
// ↑↑↑之所以向下转型成功,是因为_animal本就是Cat,属于还原;
// -----------
// 动物有可能不是猫,转型可能出错
_animal = new Dog();
_cat = (Cat) _animal;// ClassCastException
// 即使是单纯的父类实例对象,向下转型也会失败
_animal = new Animal();
_cat = (Cat) _animal;// ClassCastException
}
}
class Animal {
}
class Cat extends Animal {
}
class Dog extends Animal {
}
另一个示例:String类是Object的子类
String s ="太上老君";
Object o = s;// 向上转型(自动提升)
s = (String)o;// 向下转型(强制转换)
instanceof运算符
用于判断左边的对象是否属于右边的类型(实例、子类实例)。
如果左边对象和右边类没有继承关系,编译会出错。
public class 多态转型 {
public static void main(String[] args) {
Animal _animal = new Cat();
System.out.println(_animal instanceof Cat);
System.out.println(_animal instanceof Animal);
System.out.println(_animal instanceof Dog);
System.out.println(_animal instanceof Object);
// 和String类没有继承关系,编译无法通过
// System.out.println(_animal instanceof String);
// ----------------------
// 先判断,再转换
if (_animal instanceof Cat) {
Cat _cat = (Cat) _animal;
System.out.println(_cat.getClass());
}
}
}
class Animal {
}
class Cat extends Animal {
}
class Dog extends Animal {
}
结果:
true
true
false
true
class Cat
Java基础教程——多态的更多相关文章
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础教程:面向对象编程[2]
Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...
- Java基础十一--多态
Java基础十一--多态 一.多态定义 简单说:就是一个对象对应着不同类型. 多态在代码中的体现: 父类或者接口的引用指向其子类的对象. /* 对象的多态性. class 动物 {} class 猫 ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
随机推荐
- ansible-hoc命令行
ansible一种开源的自动化工具 ansible: hoc命令行: 是一款开源的自动化运维工具 python paramiko #模拟ssh协议批量管理主机 jinja2 #模板语言,主要用来传递变 ...
- java Excel 自动调整列宽
在开发中经常需要用到对Excel文件的操作,现在根据网上的资料整理如下: import java.io.FileOutputStream; import org.apache.poi.hssf.use ...
- SQL Server 列存储索引 第四篇:实时运营数据分析
实时运营数据分析(real-time operational analytics )是指同时在同一张数据表上执行分析处理和业务处理.分析查询主要是对海量数据执行聚合查询,而事务主要是指对数据表进行少量 ...
- C# 泛型的协变
class Program { static void Main(string[] args) { Person person = new Person(); Person chinese2 = ne ...
- LWJGL3的内存管理,第三篇,剩下的两种策略
LWJGL3的内存管理,第三篇,剩下的两种策略 上一篇讨论的基于 MemoryStack 类的栈上分配方式,是效率最高的,但是有些情况下无法使用.比如需要分配的内存较大,又或许生命周期较长.这时候就可 ...
- 万亿级KV存储架构与实践
一.KV 存储发展历程 我们第一代的分布式 KV 存储如下图左侧的架构所示,相信很多公司都经历过这个阶段.在客户端内做一致性哈希,在后端部署很多的 Memcached 实例,这样就实现了最基本的 KV ...
- MIT 6.S081 Lab5 Copy-On-Write Fork
前言 最近绝大多数的空闲时间都拿来锤15-445了,很久没动6.S081.前几天回头看了一下一个月前锤完的Lazy Allocation,自己写的代码几乎都不认识了.......看来总结之类的东西最好 ...
- (3)ASP.NET Core3.1 Ocelot认证
1.认证 当客户端通过Ocelot访问下游服务的时候,为了保护下游资源服务器会进行认证鉴权,这时候需要在Ocelot添加认证服务.添加认证服务后,随后使用Ocelot基于声明的任何功能,例如授权或使用 ...
- Aps.Net Core3.1 WebApi发送阿里云短信验证码
1.前言 转眼又要过了一年了 好久没写博客了,人不学就要落后,今天有时间把以前弄的发送阿里云短信验证码登录记录一下. 2.准备条件 1)去阿里云官网注册一个账号.有账号直接登录就行,以前新人好像有免费 ...
- Python学习笔记1:基础
1.编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 你也可以为源文件指定不同的字符编码.在 #! 行(首行)后插入至少一行特殊的注释行来定义 ...