java 继承里的构造函数和构造代码块

来源:互联网 发布:js tr ctrl 左键 监听 编辑:程序博客网 时间:2024/06/05 20:34
class Test{public static void main(String[] args) {Zi zi=new Zi();}}class Fu{static{System.out.println("Fu类静态代码块");}{System.out.println("Fu类构造代码块");}Fu(){System.out.println("Fu类构造函数");}}class Zi extends Fu{static{System.out.println("Zi类静态代码块");}{System.out.println("Zi类构造代码块");}Zi(){//super();System.out.println("Zi类构造函数");}}
/*运行结果Fu类静态代码块Zi类静态代码块Fu类构造代码块Fu类构造函数Zi类构造代码块Zi类构造函数*/

上面一段代码是一个很简单的逻辑代码  因为存在位置的不同 static修饰的静态代码块随类的加载而存在 而要加载Zi类 就必须先加载Fu类

 所以首先要执行Fu类的静态代码块 然后再执行Zi类的静态代码块

然后在这里 就一个问题 我有了想法

构造代码块是先于构造函数执行的(没名字的比有名字的快) 我们创建对象是 new的构造函数 那么按照逻辑走 我这里创建了一个子类对象

然后就跑到了子类的无参构造方法 因为我们有一个构造代码块 所以要先执行构造代码块的语句 打印 "Zi类构造代码块"然后进入子类构造函数

这里JVM在执行我们的构造函数时 其实是有一句隐式的 super()执行父类的构造方法 然后我们又有父类的构造代码块 所以就会先打印 "Fu类构造代码块"

然后再进Fu构造方法(这里的隐式super()调用的是Object超类的构造方法) 打印 "Fu类构造函数" 然后再回到Zi类构造函数执行语句 打印 "Zi类构造函数"

那么 此时就出现了问题 打印顺序就应该是

Fu类静态代码块
Zi类静态代码块
Zi类构造代码块
Fu类构造代码块
Fu类构造函数
Zi类构造函数

但是事实并不是这样的 那么是哪里出现了问题呢 就这个问题我的同窗和老师也发生了激烈的知识碰撞 但是老师始终说服不了同窗

然后我就在想 为什么会先执行构造代码块?

我们创建对象时明明是调用的构造函数 按处理逻辑来看 我们并没有调用 而没有调用它又是怎么执行的呢?

然后我就想到了

是不是对有没有构造代码块这个判定 其实是在构造方法里的呢?如果有,我就倒回去执行构造代码块 有可能!

然后我就想 如果要判定 然后先执行构造代码块 那么这里的判定语句位置一定很靠前

而JVM给我们的隐式super()调用父类构造方法是要在子类构造方法的第一句的

那么是不是这个判定其实是封装在super()方法的底层呢?执行顺序低于调用父类构造方法 所以才会出现这样的结果

但是我又想了一下super的用法以及定义 表示父类对象,所以这样想来 其实就是一个引用对象 不应该包含任何方法函数

不然在子类调用父类成员或方法还要执行这些判定 所以这个判定就不应该在super里

但是一定低于super()的执行顺序 高于一般手写代码顺序 可能在第二位 第三位甚至其他的之哟啊优先级高于我们所敲的打印语句

是JVM的又一个类似于super()的隐式方法 

这样想就能得到正确的执行顺序 我们再来理一次顺序

创建Zi对象先调用Zi的构造方法 然后遇到super()转到Fu的构造方法 执行Fu的构造方法的时候 就进行判断 有没有构造代码块?

有的 然后调用构造代码块 执行Fu类构造代码块打印语句 继续往下走 打印Fu类构造方法

然后继续执行Zi类的构造函数 判定you没有构造代码块>

依然是有的 所以执行Zi类构造代码块 然后执行Zi类构造函数

这样一来 我们就得到了正确答案 并且理清楚了继承中静态代码块 构造代码块 构造函数的执行顺序


以上言论仅个人所想 如有错误 劳驾指出 ---------------------------java初学者

原创粉丝点击