java继承会犯的小错误
注意事项:阅读本文前应该先了解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继承会犯的小错误的更多相关文章
- 【转】十个JavaScript中易犯的小错误,你中了几枪?
目录 常见错误一:对于this关键词的不正确引用 常见错误二:传统编程语言的生命周期误区 常见错误三:内存泄露 常见错误四:比较运算符 常见错误五:低效的DOM操作 常见错误6:在for循环中的不正确 ...
- 十个JavaScript中易犯的小错误,你中了几枪?
序言 在今天,JavaScript已经成为了网页编辑的核心.尤其是过去的几年,互联网见证了在SPA开发.图形处理.交互等方面大量JS库的出现. 如果初次打交道,很多人会觉得js很简单.确实,对于很多有 ...
- Java开发者常犯的十个错误
翻译自:Top 10 Mistakes Java Developers Make 文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开 ...
- java继承与覆写小练习
最近学习java到了继承的部分,写个小程序用以巩固. import java.util.Scanner;//导入输入包public class testfather { public static v ...
- Java初学者容易犯的代码错误
1. 不会判断空 空指针异常是所有Java初学者接触最多的异常,没有之一.原因是,你们拿到一个对象后容易不假思索的直接使用(直接给这个对象的属性赋值,直接调用这个对象的方法等),不报异常才怪呢!下面是 ...
- 关于TextView的setText()与Integer之间一个易犯的小错误
[转载]原文:https://my.oschina.net/xybob/blog/59524 先上图: TextView的setText()函数的两个重载函数 因为TextView有两个不同的重载函数 ...
- springMVC 配置中易犯的小错误
搭建springMVC环境时有可能遇到:'警告: No mapping found for HTTP request with URI [/WEB-INF/pages/helloWorld.jsp] ...
- iOS开发过程中易犯的小错误
addGestureRecognizer(_:) 一个手势对象只绑定一个view // 只有最后一个imgv有点击事件 let tap = UITapGestureRecognizer(target: ...
- 关于Java中的继承和组合的一个错误使用的例子
[TOC] 关于Java中的继承和组合的一个错误使用的例子 相信绝大多数人都比较熟悉Java中的「继承」和「组合」这两个东西,本篇文章就主要就这两个话题谈论一下.如果我某些地方写的不对,或者比较幼稚, ...
随机推荐
- 【Hadoop离线基础总结】Sqoop数据迁移
目录 Sqoop介绍 概述 版本 Sqoop安装及使用 Sqoop安装 Sqoop数据导入 导入关系表到Hive已有表中 导入关系表到Hive(自动创建Hive表) 将关系表子集导入到HDFS中 sq ...
- JS作用域和变量提升看这一篇就够了
作用域是JS中一个很基础但是很重要的概念,面试中也经常出现,本文会详细深入的讲解这个概念及其他相关的概念,包括声明提升,块级作用域,作用域链及作用域链延长等问题. 什么是作用域 第一个问题就是我们要弄 ...
- SpringMVC中参数的传递(一)
前言 1.首先,我们在web.xml里面配置前端控制器DispatcherServlet以及字符编码过滤器(防止中文乱码),配置如下: <?xml version="1.0" ...
- java -> 异常类与自定义异常
异常 什么是异常?Java代码在运行时期发生的问题就是异常. 在Java中,把异常信息封装成了一个类.当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置.原因等). 异常的继承体 ...
- ql的python学习之路-day10
前言:本节主要讲解迭代器和生成器 迭代器&生成器 一.生成器(generator) 循环占用大部分的容量内存,如果只需要循环前面的几个结果那怎么样做呢,在python中有一种一边循环一边计算的 ...
- 00005-js 获取uuid
admin.guid = function () { function S4() { return (((1+Math.random())*0x10000)|0).toString(16).subst ...
- 记一条distinct 语句的优化。
语句是这条 SELECT DISTINCT bank, account FROM sdb_payments WHERE status="succ": status 上有索引,但不是 ...
- 【雕爷学编程】MicroPython动手做(02)——尝试搭建K210开发板的IDE环境
喜欢今日头条,偶然看到广告,半个多月前交了8.9元,报名参加了头条上Python的四天培训课,呵呵,总算是有了零的开始(还是有点收获的,见https://www.sohu.com/a/38112874 ...
- node响应头缓存设置
我把react项目分成4个板块,在路由的顶层 今天在手机上打开react项目的时候,发现平级路由跳转时某一个图片较多的板块图片总是渲染得很慢,这分明是重新发起请求了. 然后我先查一下react-rou ...
- gRPC负载均衡(自定义负载均衡策略)
前言 上篇文章介绍了如何实现gRPC负载均衡,但目前官方只提供了pick_first和round_robin两种负载均衡策略,轮询法round_robin不能满足因服务器配置不同而承担不同负载量,这篇 ...