Java继承中构造器的调用原理
Java的继承是比较重要的特性,也是比较容易出错的地方,下面这个例子将展示如果父类构造器中调用被子类重写的方法时会出现的情况:
首先是父类:
public class test {
void fun(){
System.out.println("test fun()");
}
void fun1(){
System.out.println("test fun1()");
}
test(){
fun();
fun1();
}
public static void main(String[] args) {
test t =new test();
}
}
这里父类的构造器将调用一个fun方法,main函数的运行结果是:
test fun()
test fun1()
然后是子类:
public class test2 extends test {
int i = 2;
test2(){
fun();
}
void fun(){
System.out.println("test2 fun()");
System.out.println(i);
}
public static void main(String[] args) {
test2 t = new test2();
}
}
子类增加了一个字段i并初始化为2,并重写了fun方法,不仅打印的字符串不一样,还加了打印i的功能,构造器和父类一样调用了fun方法。main函数的运行结果是:
test2 fun()
0
test fun1()
test2 fun()
2
通常java的类进行初始化的时候,会先进行父类的初始化,所以会先调用父类的构造器,再进行子类的初始化,调用子类的构造器。
一开始写完代码我以为的结果是:
test fun()
test fun1()
test2 fun()
2
我以为就算父类的方法被重写了,也会调用自己的方法,但事实告诉我们,父类初始化过程中构造器如果调用了被子类重写的方法,会调用被子类重写的方法。
还有一点,如果子类重写的方法中使用了子类才定义的字段,那这个字段的值将是该字段类型的默认值。
所以类的初始化流程总结(继承相关)就是:
1.为对象分配的存储空间初始化为二进制零。
2.调用父类的构造器,如果调用被覆盖的方法,被覆盖的方法将被调用,如果使用了子类中才定义的字段,该字段的值为该字段类型的默认值。
3.调用子类的构造器。
(这里总结的初始化流程只总结了继承相关的,正常的static部分、初始化代码还是正常的样子)
为什么会出现这种情况呢,为什么需要先为对象的存储空间初始化为二进制零呢?
1.在继承中构造器的调用是分级的,先调用父类的,父类如果有父类就父类的。。。这一步是通过动态绑定实现的。
2.从概念上来说,构造器是用来初始化对象的,但是像上面那种情况,子类重写了父类的方法,使得父类将使用子类的成员,但是此时正在初始化父类,子类还没有进行初始化。
3.基于以上两点就将为对象分配的存储空间初始化为二进制零。
所以重写父类的方法的时候需要考虑到这个特性,这种特性可能会导致父类的初始化出现问题。
Java继承中构造器的调用原理的更多相关文章
- Java 继承中构造方法的执行顺序问题
在Java中,如果一个类没有任何显式创建的构造器则该类默认会有一个无参构造器:如果显式创建了有参构造器则该类就不再有默认无参构造器. 在Java继承中,构造器并不能被继承,而是被显示或隐式调用. 1. ...
- JAVA 继承中的this和super
学习java时看了不少尚学堂马士兵的视频,还是挺喜欢马士兵的讲课步骤的,二话不说,先做实例,看到的结果才是最实际的,理论神马的全是浮云.只有在实际操作过程中体会理论,在实际操作过程中升华理论才是最关键 ...
- 转转转!java继承中的this和super
学习java时看了不少尚学堂马士兵的视频,还是挺喜欢马士兵的讲课步骤的,二话不说,先做实例,看到的结果才是最实际的,理论神马的全是浮云.只有在实际操作过程中体会理论,在实际操作过程中升华理论才是最关键 ...
- ecshop中ajax的调用原理 1
ecshop中ajax的调用原理 1:首先ecshop是如何定义ajax对象的. ecshop中的ajax对象是在js/transport.js文件中定义的.里面是ajax对象文件.声明了一个va ...
- ECSHOP中ajax的调用原理
ECSHOP中ajax的调用原理 ecshop中ajax的调用原理. 1.首先ecshop是如何定义ajax对象的. ecshop中的ajax对象是在js/transport.js文件中定义的.里面是 ...
- java中构造器的调用顺序
在编程的过程中,我们经常会遇到多个类的继承问题,那么多个类的构造器是按照什么顺序调用的呢? 先看一段代码: public class Meal { public Meal() { System.out ...
- 【Java学习笔记之二十】final关键字在Java继承中的用法小结
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...
- Java继承中的转型及其内存分配
看书的时候被一段代码能凌乱啦,代码是这样的: package 继承; abstract class People { public String tag = "疯狂Java讲义"; ...
- [Java] 继承中,父类被覆盖的成员变量、方法的可访问性
在 Java 的继承机制里,在子类内部,可以访问父类被覆盖的变量和方法:在子类外部,可以访问父类的被覆盖变量,但是不能访问父类的被覆盖方法. 父类中被覆盖的方法不能在外部被方法,这是出于封装的考虑. ...
随机推荐
- TPO3-2 Depletion of Ogallala Aquifer
Estimates indicate that the aquifer contains enough water to fill Lake Huron, but unfortunately, und ...
- Java 的 ArrayList 的底层数据结构
1. 数据结构--ArrayList源码摘要 ublic class ArrayList<E> extends AbstractList<E> implements List& ...
- 剖析String,StringBuffer,StringBuilder异同
近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下,便 ...
- python自动化测试之函数(匿名函数lambda和三目运算等(高级用法))
''' 匿名函数: lambda ''' def Add(a,b): print(a+b) Add(2,3) per = lambda a,b:a+b print(per(2,3)) ''' 三目运算 ...
- TortoiseSVN配置和使用教程
2009-04-24 来源:dev.idv.tw 1 安装及下载client 端 2 什么是SVN(Subversion)? 3 为甚么要用SVN? 4 怎么样在Windows下面建立SVN Repo ...
- Twitter类社交平台 用比例建立新的“好坏”与社会焦点
用比例建立新的"好坏"与社会焦点" title="Twitter类社交平台 用比例建立新的"好坏"与社会焦点"> 互联网全面 ...
- 对这些工程师来说,Skype Translator是他们自己的事——Skype Translator项目研发团队的故事
Translator是他们自己的事--Skype Translator项目研发团队的故事" title="对这些工程师来说,Skype Translator是他们自己的事--Sky ...
- <HAOI2008>硬币购物
和神奇dp的战斗 还有容斥原理 终于get到了 #include<cstdio> #include<cstring> #include<iostream> #inc ...
- CentOS使用epel安装不同版本php-fpm
针对CentOS使用epel安装 yum -y install epel-release安装好后可以通过如下命令查看yum info epel-releaseyum repolist查看php版本ph ...
- (为容器分配独立IP方法二)通过虚拟IP实现docker宿主机增加对外IP接口
虚拟IP.何为虚拟IP,就是一个未分配给真实主机的IP,也就是说对外提供数据库服务器的主机除了有一个真实IP外还有一个虚IP,使用这两个IP中的任意一个都可以连接到这台主机,所有项目中数据库链接一项配 ...