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继承中构造器的调用原理的更多相关文章

  1. Java 继承中构造方法的执行顺序问题

    在Java中,如果一个类没有任何显式创建的构造器则该类默认会有一个无参构造器:如果显式创建了有参构造器则该类就不再有默认无参构造器. 在Java继承中,构造器并不能被继承,而是被显示或隐式调用. 1. ...

  2. JAVA 继承中的this和super

    学习java时看了不少尚学堂马士兵的视频,还是挺喜欢马士兵的讲课步骤的,二话不说,先做实例,看到的结果才是最实际的,理论神马的全是浮云.只有在实际操作过程中体会理论,在实际操作过程中升华理论才是最关键 ...

  3. 转转转!java继承中的this和super

    学习java时看了不少尚学堂马士兵的视频,还是挺喜欢马士兵的讲课步骤的,二话不说,先做实例,看到的结果才是最实际的,理论神马的全是浮云.只有在实际操作过程中体会理论,在实际操作过程中升华理论才是最关键 ...

  4. ecshop中ajax的调用原理 1

    ecshop中ajax的调用原理   1:首先ecshop是如何定义ajax对象的. ecshop中的ajax对象是在js/transport.js文件中定义的.里面是ajax对象文件.声明了一个va ...

  5. ECSHOP中ajax的调用原理

    ECSHOP中ajax的调用原理 ecshop中ajax的调用原理. 1.首先ecshop是如何定义ajax对象的. ecshop中的ajax对象是在js/transport.js文件中定义的.里面是 ...

  6. java中构造器的调用顺序

    在编程的过程中,我们经常会遇到多个类的继承问题,那么多个类的构造器是按照什么顺序调用的呢? 先看一段代码: public class Meal { public Meal() { System.out ...

  7. 【Java学习笔记之二十】final关键字在Java继承中的用法小结

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...

  8. Java继承中的转型及其内存分配

    看书的时候被一段代码能凌乱啦,代码是这样的: package 继承; abstract class People { public String tag = "疯狂Java讲义"; ...

  9. [Java] 继承中,父类被覆盖的成员变量、方法的可访问性

    在 Java 的继承机制里,在子类内部,可以访问父类被覆盖的变量和方法:在子类外部,可以访问父类的被覆盖变量,但是不能访问父类的被覆盖方法. 父类中被覆盖的方法不能在外部被方法,这是出于封装的考虑. ...

随机推荐

  1. ef codefirst VS里修改数据表结构后更新到数据库

    2.根据已建立table的数据库建立ADO.NET数据模型在修改表后进入 工具->nuget包管理器->程序包管理器控制台 输入  enable-migrations   后vs会添加一个 ...

  2. go proxy转发工作中碰到的问题

    A-B 需求是一个中转 A-Proxy-B 读取来源请求A,在proxy读取body作些处理,再转给B,再把返回内容转给A 问题出在proxy这里 如果先把请求给B,再读body res, err : ...

  3. ORs-5-OR Subgenomes Variation among Birds, Sea Turtle and Alligator

    OR Subgenomes Variation among Birds, Sea Turtle and Alligator 由 该图数据计算每种鸟的relative percentage,得到下图: ...

  4. 关于RFC

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/byxdaz/article/details/557902关于RFC(Request For Comm ...

  5. VM Storage Policies深度解析

  6. 【转】【关于 A^x = A^(x % Phi(C) + Phi(C)) (mod C) 的若干证明】【指数循环节】

    [关于 A^x = A^(x % Phi(C) + Phi(C)) (mod C) 的若干证明][指数循环节] 原文地址:http://hi.baidu.com/aekdycoin/item/e493 ...

  7. 杂谈php之什么是cgi,fastcgi,fpm,cli,mod

    杂谈PHP极少关注的问题 本话题来自于我使用PHP进行网页爬虫的一次经历.对于一个web开发者来说,PHP解释器本身却知之甚小,实在是惭愧呐! 首先这个话题要从几个提问开始. PHP是什么? 外文名: ...

  8. java MVC 自定义类型转换器(Formatter、AnnotationFormatterFactory)

    下面一个事例,是将传入的一个身份证号,转换成一个对象(提取身份证号的地址.出身日期.性别等) 实体类 Person 有三个字段如下: String province; //地址 Date birthd ...

  9. GYOJ_1812_股票(stock)

    题目描述 2130年,股神巴菲特投胎了!他投胎到你身上! 你作为股神转世,能力比原股神还要强,你可以预测到今后n天的股价.假设刚开始你的手上有1元钱,你想知道n天后你最多可以赚到多少钱.作为股神转世, ...

  10. 吴裕雄--天生自然KITTEN编程:一箭穿心