java小心机(6)| 多态的一些坑
对于"多态"的概念,想必大家都很熟悉了,但我们还是来回顾一下吧
class Actor {
public void act(){
System.out.println("Actor");
}
}
class HappyActor extends Actor{
@Override
public void act() {
System.out.println("HappyActor");
}
}
class SadActor extends Actor{
@Override
public void act() {
System.out.println("SadActor");
}
}
public class Test {
public static void main(String[] args) {
Actor hActor = new HappyActor();//向上转型
Actor sActor = new SadActor();//向上转型
hActor.act();
sActor.act();
}
}
//out:
HappyActor
SadActor
上面例子中,HappyActor和SadActor都继承Actor并重写了act方法,在main函数中,两个Actor对象调用相同方法产生不同的结果,就称为"多态"。
在设计程序中,"多态"可使代码变得灵活,有时候还是很好使得,但也有一些坑在里面,下面就给你一一道来
坑1 "覆盖"私有方法
public class PrivateOverride {
private void f(){
System.out.println("private f()");
}
public static void main(String[] args){
PrivateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride{
public void f(){
System.out.println("public f()");
}
}
//out:
private f()
我们期望输出的是public f(),但结果并非我们所想。PrivateOverride中的f()方法是私有的,对它的子类是不可见的,Derived 的f()方法无法覆盖它。
结论:无法覆盖私有方法。需要注意,子类中方法切勿与父类中的私有方法同名,否则会容易混淆。
坑2 域与静态方法不存在多态
1. 域
class SuperClass {
public String field = "Super field";
public String getField() {
return field;
}
}
class SubClass extends SuperClass {
public String field = "Sub field";
@Override
public String getField() {
return field;
}
public String getSuperField() {
return super.getField();
}
}
public class FieldAccess {
public static void main(String[] args) {
SuperClass sup = new SubClass();//向上转型
System.out.println("sup.field = " + sup.field
+ ", sup.getField() = " + sup.getField());
SubClass sub = new SubClass();
System.out.println("sub.field = " + sub.field
+ ", sub.getField() = " + sub.getField()
+", sub.getSuperField() = " + sub.getSuperField());
}
}
//out:
sup.field = Super field, sup.getField() = Sub field
sub.field = Sub field, sub.getField() = Sub field,
sub.getSuperField() = Super field
域的访问操作是由编译器解析的,所以不是多态的。(扩展:多态是由动态绑定实现的,即是在程序运行期对数据做绑定)
SuperClass中的field和SubClass中的field分配了不同的内存空间,在SubClass中实际上包含了两个field:一个是自己的和从父类SuperClass中继承的。子类SubClass中可使用super.field显示地指明SuperClass中的field。
2. 静态方法
class StaticSuper{
public static String staticGet(){
return "Base staticGet()";
}
public String dynamicGet(){
return "Base dynamicGet()";
}
}
class StaticSub extends StaticSuper{
public static String staticGet(){
return "Base staticGet()";
}
@Override
public String dynamicGet(){
return "Base dynamicGet()";
}
}
public class StaticMethod {
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet());
System.out.println(sup.dynamicGet());
}
}
//out:
Base staticGet()
Base dynamicGet()
静态方法无法被覆盖,无法实现多态。
总结:域与静态方法都无法实现多态。需要注意,尽可能不对父类和子类的域使用相同的名字,无法覆盖的方法不使用相同名字,以免造成混淆。
推荐阅读:
您的点赞、转发是对我最大的支持!
THANDKS
- End -
一个立志成大腿而每天努力奋斗的年轻人
伴学习伴成长,成长之路你并不孤单!
java小心机(6)| 多态的一些坑的更多相关文章
- java小心机(5)| 浅谈类成员初始化顺序
类成员什么时候会被初始化呢?一般来说:"类的代码在初次使用时才被加载",加载过程包括了初始化. 比如说new A()调用构造函数时,类中全部成员都会被初始化. 但对于static域 ...
- java小心机(3)| 浅析finalize()
每天进步一丢丢,连接梦与想 如果你停止就是谷底,如果你还在努力就是上坡 系列文章 java"小心机"(1)[资源彩蛋!] java小心机(2)| 重载和构造器的小细节 预备知识 J ...
- java小心机(2)| 重载和构造器的小细节
每天进步一点点,距离大腿又近一步! 阅读本文大概需要10分钟 java小心机,为你诉说java鲜为人知的一面 涉及基本数据类型的重载 基本类型能从一个"较小"的类型自动提升到&qu ...
- java"小心机"(1)【资源彩蛋!】
每天进步一点点,距离大腿又近一步! 阅读本文大概需要9分钟 java"小心机"系列文章在此开篇.在这,将会给你带来曾经错过.忽略或感到模糊的知识,也许它很基础,微不足道,但它能修复 ...
- java小心机(4)| 继承与组合的爱恨情仇
在java中,有两种主要复用代码的方法:继承和组合. 继承,是OOP的一大特性,想必大家都非常熟悉了;组合,其实也很常见,只是不知道它的名字罢了. 继承 子类拥有父类的基本特性,需使用extend关键 ...
- Java基础学习小记--多态
题外话:总结了多年的学习心得,不得不说,睡眠是一个学习者的必需品!所谓"早起毁一天"不是没有道理哪,特别对Coders来说,有几天不是加班到夜里.好吧,我承认对于初学Java的我, ...
- java基础不牢固容易踩的坑
java基础不牢固容易踩的坑 经过一年java后端代码以及对jdk源码阅读之后的总结,对java中一些基础中的容易忽略的东西写下来,给偏爱技术热爱开源的Coder们分享一下,避免在写代码中误入雷区. ...
- 寒假答辩作品:Java小游戏
目录 java入门小游戏[test] 游戏界面 前言 (可直接跳到程序介绍) 前期入门小项目 前期收获 后期自创关卡 后续 java入门小游戏[test] 游戏界面 github地址: https:/ ...
- java提高篇之理解java的三大特性——多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
随机推荐
- MySQL查询语句积累
#查询名字中带李且名字是两个字的所有学生信息 SELECT * FROM user_test WHERE user_name LIKE '李_';
- C++,Windows/MFC_中L和_T()之区别
字符串前面加L表示该字符串是Unicode字符串._T是一个宏,如果项目使用了Unicode字符集(定义了UNICODE宏),则自动在字符串前面加上L,否则字符串不变.因此,Visual C++里边定 ...
- Java面向对象程序设计第9章1-9
Java面向对象程序设计第9章1-9 1. 线程和进程的联系和区别是什么? 联系: 一个进程可以包括多个线程. 区别: 进程: 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是系统 ...
- 《提升能力,涨薪可待》-Java并发之AQS全面详解
欢迎关注公众号[Ccww笔记],原创技术文章第一时间推出 一.AQS是什么?有什么用? AQS全称AbstractQueuedSynchronizer,即抽象的队列同步器,是一种用来构建锁和同步器的框 ...
- 使用Gson中的JsonElement所遇到的坑
使用Gson中的JsonElement所遇到的坑 原文链接: https://blog.csdn.net/weixin_30326515/article/details/98196013 声明:此博客 ...
- HashMap面试题解答
一.HashMap的实现原理? 此题可以组成如下连环炮来问 你看过HashMap源码嘛,知道原理嘛?为什么用数组+链表?hash冲突你还知道哪些解决办法?我用LinkedList代替数组结构可以么?既 ...
- DEVOPS技术实践_02:jenkins自动构建项目
一.用户名密码错误 打开jenkins发现用户名密码错误,解决 1.1 找到config.xml文件 [root@jenkins-master ~]# ll -a drwxr-xr-x. root r ...
- vc++ 监控指定路径下文件变化
参考MSDN文档 https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-readdirectorychange ...
- 【题解】地精部落(DP)
[题解]地精部落(DP) 设\(f_i\)表示强制第一个是谷的合法方案数 转移枚举一个排列的最大值在哪里,就把序列分成了互不相干的两个部分,把其中\(i-1\choose j-1\)的数字分配给前面部 ...
- $HDOJ5542\ The\ Battle\ of\ Chibi$ 数据结构优化$DP$
$AcWing$ $Description$ $Sol$ 首先显然是是以严格递增子序列的长度为阶段,由于要单调递增,所以还要记录最后一位的数值 $F[i][j]$表示前$i$个数中以$A_i$结尾的长 ...