理解 Java 多态性:编译时和运行时的区别
摘要助手
切换
SummaryGPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往订阅 💥
前往评论 💬
👀 部署教程
理解 Java 多态性:编译时和运行时的区别
dong4j相同的行为, 不同的实现
多态多态, 多种状态, 而多种状态的体现就在不同的实现上面, 也可以说是不同的效果.
举个例子:
我这里有 3 个杯子, 里面都装了白酒, 你并不知道它们都是什么酒, 只有等你喝过之后才能知道, 第一个杯子是二锅头, 第二个是五粮液, 第三个是茅台.
1 | Maotai mo = new Maotai(); |
这里我们可以这样理解, 茅台是酒类的一种, 它们之间是继承关系, 当 a 指向了 mo 这个对象的时候, 它会自动向上转型为 Wine, 这也就是说 w 是可以指向茅台这个实例.
这样做的好处就是, 在继承中我们知道子类是父类的扩展, 它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能
但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们
所以对于多态我们可以总结如下:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用这些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
不过还是可以调用子类中特有的方法, 后文中将会讲到.对于面向对象而已,多态分为编译时多态和运行时多态。
- 编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。
- 运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
多态的分类
- 静态多态 (编译期确定要执行的效果, 编译器只是做语法检查)
- 重载 (Overload) 实现
- 动态多态 (编译期不知道运行效果, 而是运行期根据绑定对象的不同确定结果)
- 重写 (Override)
- 动态绑定
当一个父类引用指向子类对象的时候
为什么父类不能调用子类重载之后的方法? 为什么父类调用的方法的实现是子类重写后的实现?
- 因为重载是对于一个类而言的, 当子类继承父类, 然后在本类中重载了父类的这个方法, 对于父类而言是看不到这个在子类中重载之后的方法的, 因为它只属于子类, 所以当父类调用这个方法的时候, 因为父类中根本就没有这个方法, 所以编译器会报错;
- 然而当父类调用被子类重写的过后的方法时, 因为父类中存在同名方法, 编译器不会报错, 然后通过动态绑定, 将被调用的这个方法和子类关联起来, 所以方法实现的是子类重写过后的效果.
动态绑定
- 将一个方法调用与该方法所在的类关联起来;
- 在运行时候根据具体对象的类型绑定;
- 当父类引用指向子类的对象, 调用重写的方法时, 是调用子类中重写的方法;
转型技术 (类之间必须要有继承关系)
左右两边数据类型不一致
- 向上转型 –> 自动
Person p = new Man();
此时的引用 p 只能看见父类的方法, 而看不到子类所特有的方法 - 向下转型 –> 强制
Man m = (Man)p
此时 m 引用可以看到全部的方法, 因为 m 指向了一个 Man 对象.
这样就可以调用子类对象中访问修饰符允许的方法和属性了
多态的引用–异构 集合
创建一个不是同一类型, 但是有共同父类的数据集合, 不同对象的集合称为异构集合
多态的好处和弊端:
A: 好处
提高了程序的可维护性和可扩展性。
维护性:继承保证
扩展性:多态保证
B: 弊端
父类 / 父接口不能访问子类特有功能。
多态的体现形式:
- 具体类多态
1 | class Fu {} |
- 抽象类多态
1 | abstract class Fu {} |
- 接口多态
1 | interface Inter {} |
总结
- 使用父类类型的引用指向子类的对象;
- 该引用只能调用父类中定义的方法, 不能调用子类的特有的属性和方法;
- 如果子类中重写父类的方法, 那么调用该方法, 将会调用子类中重写后的实现;
- 在多态中, 子类可以调用父类的所有非私有方法;
- 父类的引用可以指向子类的对象, 子类的引用不能指向父类的对象;
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果