注意事项:阅读本文前应该先了解java的继承。本文定位为已经继承基础知识。

一:试图覆盖私有方法

先上代码

 public class Father {

     private void print() {
System.out.println("private print");
} public static void main(String[] args) {
Father father = new Son();
father.print();
} }
 public class Son extends Father {

     public void print() {
System.out.println("public print");
}
}

运行father的main方法,我们所期望的输出是public print,但是由于private方法默认为final方法,而且对导出子类是屏蔽的,在这种情况下,子类中的print就是子类中的一个新方法,并非是覆盖了父类的print方法,而且在子类的print方法上是无法加入@override注解的

结论:private方法无法被覆盖重写。

二:在一个构造器内部调用正在构造的对象的某个动态绑定方法

我们都知道,构造器的调用会从最高级的父类开始调用,然后不断反复递归下去。如果在父类的构造器中调用子类的构造方法输出变量,会发生什么?

 public class Father {

     public void draw() {
System.out.println("father draw");
} public Father() {
System.out.println("father:before draw");
draw();
System.out.println("father:after draw");
} }
 public class Son extends Father {

     private int number = 1;

     public Son(int number) {
this.number = number;
System.out.println("init number:" + this.number);
} @Override
public void draw() {
System.out.println("son draw number:" + this.number);
}
}
public class MainTest <T> extends Object{

    public static void main(String[] args) {
new Son(5);
} }

控制台打印:

father:before draw
son draw number:0
father:after draw
init number:5

在测试中,我们new一个son同时传一个5进去,根据构造器的调用,我们知道在构造son的时候要先调用father的构造方法,而在father的构造器中,有调用draw方法。而在子类中,draw方法是将son中的number打印出来,number有一个默认的值为1,那在draw调用过程中,我们期望的输出应该是1,但实际输出的是0.

解决这一问题的关键所在是初始化的过程。在其他任何事物发生之前,分配给对象的储存空间初始化为二进制的零(你可以这样认为,number有一个默认值为1,但是在有这个默认值之前还有一个默认值为0),然后父类的构造器开始调用,再递归调用子类的构造方法,然后按照声明的顺序初始化成员变量。而在这个初始化步骤之前,一切变量都是0,或者null。

三:调用子类覆盖的父类静态方法。

 public class Father {

     public static String staticGet() {
return "father static get";
} public String dynaminGet() {
return "father dynamin get";
}
}
 public class Son extends Father {

     public static String staticGet() {
return "son static get";
} public String dynaminGet() {
return "son dynamin get";
}
}
public class MainTest <T> extends Object{

    public static void main(String[] args) {
Father f = new Son();
System.out.println(f.staticGet());
System.out.println(f.dynaminGet());
} }

控制台输出:

father static get
son dynamin get

我们期望的输出应该都是son的方法而不是father的方法,但是调用静态方法的时候是father而不是son。这是因为如果某个方法是静态的,那么它的行为就不具有多态性,静态方法是与类绑定的,而不是与单个对象相关联的。子类并不能覆盖父类的静态方法,事实上,在son中的staticGet方法上无法添加@override注解。

四:子类的域可以覆盖父类的域

 public class Father {

     public int number = 3;

     public int getNumber() {
return number;
}
}
 public class Son extends Father {

     public int number = 2;

     public int getNumber() {
return number;
} public int getSuperNumber() {
return super.number;
}
}
public class MainTest <T> extends Object{

    public static void main(String[] args) {
Son s = new Son();
System.out.println(s.getNumber());
System.out.println(s.getSuperNumber());
} }

控制台输出:

2
3

如果son中的number覆盖掉father的number,那么输出的两个number都应该是2,事实上从son中得到father的number为3,这说明son中的number并没有覆盖掉father中的number。在本例中,son.number和father.number分配到了不同的储存空间。换句话来说,在son中其实包含了两个名为number的变量:它自己的和从father中继承得到的。然而在son中的number所产生的默认域并非father中的number域。因此,为了得到father中的number,必须显式地指明super.field。

java继承会犯的小错误的更多相关文章

  1. 【转】十个JavaScript中易犯的小错误,你中了几枪?

    目录 常见错误一:对于this关键词的不正确引用 常见错误二:传统编程语言的生命周期误区 常见错误三:内存泄露 常见错误四:比较运算符 常见错误五:低效的DOM操作 常见错误6:在for循环中的不正确 ...

  2. 十个JavaScript中易犯的小错误,你中了几枪?

    序言 在今天,JavaScript已经成为了网页编辑的核心.尤其是过去的几年,互联网见证了在SPA开发.图形处理.交互等方面大量JS库的出现. 如果初次打交道,很多人会觉得js很简单.确实,对于很多有 ...

  3. Java开发者常犯的十个错误

    翻译自:Top 10 Mistakes Java Developers Make 文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开 ...

  4. java继承与覆写小练习

    最近学习java到了继承的部分,写个小程序用以巩固. import java.util.Scanner;//导入输入包public class testfather { public static v ...

  5. Java初学者容易犯的代码错误

    1. 不会判断空 空指针异常是所有Java初学者接触最多的异常,没有之一.原因是,你们拿到一个对象后容易不假思索的直接使用(直接给这个对象的属性赋值,直接调用这个对象的方法等),不报异常才怪呢!下面是 ...

  6. 关于TextView的setText()与Integer之间一个易犯的小错误

    [转载]原文:https://my.oschina.net/xybob/blog/59524 先上图: TextView的setText()函数的两个重载函数 因为TextView有两个不同的重载函数 ...

  7. springMVC 配置中易犯的小错误

    搭建springMVC环境时有可能遇到:'警告: No mapping found for HTTP request with URI [/WEB-INF/pages/helloWorld.jsp] ...

  8. iOS开发过程中易犯的小错误

    addGestureRecognizer(_:) 一个手势对象只绑定一个view // 只有最后一个imgv有点击事件 let tap = UITapGestureRecognizer(target: ...

  9. 关于Java中的继承和组合的一个错误使用的例子

    [TOC] 关于Java中的继承和组合的一个错误使用的例子 相信绝大多数人都比较熟悉Java中的「继承」和「组合」这两个东西,本篇文章就主要就这两个话题谈论一下.如果我某些地方写的不对,或者比较幼稚, ...

随机推荐

  1. Coursera课程笔记----计算导论与C语言基础----Week 10

    C程序中的数组(Week 10) 一维数组 数组的定义 类型 数组名[常量表达式] int sheep[10] 定义数组时,[]内必须为常量表达式 可以用const int 可以在main函数前,#d ...

  2. 【2020Java最新学习路线】写了很久,这是一份最适合普通大众、科班、非科班的路线

    点赞再看,养成习惯,微信搜索[三太子敖丙]关注这个互联网苟且偷生的工具人. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的 ...

  3. java1.8新特性之stream

    什么是Stream? Stream字面意思是流,在java中是指一个来自数据源的元素队列并支持聚合操作,存在于java.util包中,又或者说是能应用在一组元素上一次执行的操作序列.(stream是一 ...

  4. HttpClient之Post接口代码范例

    核心包: import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject; 一:接收数据 json数据格式如下 ...

  5. Qt5.5 connection firebird on Linux Centos7.2 or windows

    windows c++ 项目移植到 linux,原项目需要连接 Firebird数据库. google 后知道 linux qt connection Firebird 有两种方法: 1.ibpp c ...

  6. Python内置函数列表

    函数 用途 abs() 返回数字绝对值 all() 判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False any() 判断给定的可迭代参数 ...

  7. 推荐一款Python神器,5 行 Python 代码 实现一键批量扣图

    今天给大家分享一款Python装逼实用神器. 在日常生活或者工作中,经常会遇到想将某张照片中的人物抠出来,然后拼接到其他图片上去.专业点的人可以使用 PhotoShop 的"魔棒" ...

  8. kafka消费者重试逻辑的实现

    背景 在kafka的消费者中,如果消费某条消息出错,会导致该条消息不会被ack,该消息会被不断的重试,阻塞该分区的其他消息的消费,因此,为了保证消息队列不被阻塞,在出现异常的情况下,我们一般还是会ac ...

  9. Apache自定义404

    先用命令找到httpd.conf文件在哪 find -name 'httpd.conf' 默认配置文件: vim /etc/httpd/conf/httpd.conf 然后找到项目的路径 <Di ...

  10. MySQL慢查询优化(线上案例调优)

    文章说明 这篇文章主要是记录自己最近在真实工作中遇到的慢查询的案例,然后进行调优分析的过程,欢迎大家一起讨论调优经验.(以下出现的表名,列名都是化名,实际数据也进行过一点微调.) PS:最近做了一个面 ...