《零基础学 Java》 FAQ 之 11- 为什么构造方法中调用重载的构造方法必须得是在第一行
@甜~ 在构造方法一节问到
老师,为什么构造方法中调用重载的构造方法,必须得是在第一行,有什么特殊考虑吗
DNT 回复:我好像在视频里提过一句, 但是是在后面讲解 super 的时候. 如果不从继承关系的角度看, 让 this 放在第一行确实是没有硬道理的.
回答
后面讲到 super 的时候, 也就是下面两节:
71 | super:和父类对象沟通的桥梁
72 | super:调用父类的构造方法
会讲到, 子类的构造方法, 会强制在第一行调用父类的构造方法. 这一点和 this 要在第一行有关联. 而这一点, 也正是给了构造方法调用别的构造方法, 必须是第一行给了一个强理由.
首先说一下为什么"子类的构造方法, 会强制在第一行调用父类的构造方法", 这个我在视频里提了一句, (人工划重点)这是因为子类可以访问父类的方法和属性. 那么必须保证子类的对象在做任何事情之前, 子类里那个隐含的父类对象, 必须初始化完成. 否则, 初始化都没完成, 调用方法, 返回属性, 都可能得到的是不对的状态/值(人工划重点结束).
那么这里说的初始化是什么呢?就是给对象里的属性设置正常的值,或者执行一些方法。简单来说,创建一个对象可以分为两步,一步是在堆上分配内存,然后在这个内存里存储对象的属性。下一步就是初始化对象,也就是执行构造方法。只有执行完毕构造方法,这个对象才算是可以被使用了。
这里可能有的一个疑问是,对象都创建出来了,初始化不初始化的不都能用么?其实不是那么回事儿。对象初始化可以做的事情很多,比较普遍的是初始化属性的值,也可能会调用一些方法,完成一些业务逻辑要求的初始化代码。从业务逻辑上来说,对象没有初始化完,是不应该被使用的。
举个例子,在堆上分配内存,就是买了一堆电脑硬件,什么内存,CPU,硬盘主板。初始化就是把这些零件拼装起来,组成一个电脑,并且给它装上操作系统。在完成初始化之前,电脑不是能被使用的电脑,只是一堆零件。同样的道理,在完成初始化之前,对象也不是对象,只是一堆内存。
好, 知道了这一点之后, 很自然的可以推出, this 调用必须也在第一行, 否则的话, this 调用里会调用父类构造方法, 如果 this 不是第一句, 那么也就隐含着调用父类构造方法不是第一句, 也就是说, 子类可能使用的父类的属性或者方法是没有初始化完成的.
其实我也觉得这个挺别扭, 拿参数稍微算一下,再给构造方法不行吗? 但是这个确实很难控制, 或者说没必要做这么复杂. 是给自己挖坑. 所以干脆一刀切, super 必须是第语句, this 也必须是第一句.
这篇文章来自极客时间推出的《零基础学Java》中的 FAQ。除了在每节视频课下方回答大家的问题之外,针对大家提出的优质问题或者普遍问题,如果需要更大篇幅的文章解答,则会在 FAQ 中以文章的方式给出回答。带你零基础入门,夯实 Java,课程地址:https://time.geekbang.org/course/intro/181
版权声明: 本文为 InfoQ 作者【臧萌】的原创文章。
原文链接:【http://xie.infoq.cn/article/2c694af11c66477fb82d7cbab】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论