详解Java构造方法为什么不能覆盖,我的钻牛角尖病又犯了....

看Think in Java,遇到个程序

class Egg2 {
    protected class Yolk {
        public Yolk() {
            System.out.println("Egg2.Yolk()");
        }

        public void f() {
            System.out.println("Egg2.Yolk.f()");
        }
    }

    private Yolk y = new Yolk();

    public Egg2() {
        System.out.println("New Egg2()");
    }

    public void insertYolk(Yolk yy) {
        y = yy;
    }

    public void g() {
        y.f();
    }
}

public class BigEgg2 extends Egg2 {
    public class Yolk extends Egg2.Yolk {
        public Yolk() {
            System.out.println("BigEgg2.Yolk()");
        }

        public void f() {
            System.out.println("BigEgg2.Yolk.f()");
        }
    }

    public BigEgg2() {
        insertYolk(new Yolk());
    }

    public static void main(String[] args) {
//        Egg2 e1 = null;
//        Egg2 e2 = new BigEgg2();
//        new Egg2();
          new BigEgg2();
//        e2.g();
    }
} ///:~

输出

Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()

其实基本上我根据后面的几个注释,也大概明白了看的顺序构造顺序是什么,见图

 构造顺序图

但是,看了输出,我就纳闷为什么,为什么第三行不是BigEgg2.Yolk(),不能覆盖吗?

Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()

分析一下

BigEgg2是Egg2的子类,他们都有Yolk的内部类,而且BigEgg2.Yolk继承了Egg2.Yolk。注意此处,同名类可以继承。

那么,他们构造方法为什么不能覆盖,都是Public Yolk(){}。

当然,网上都说子类继承父类除构造方法以外的所有方法,但这是结果,我要知道为什么!!

先说几个错误的观点

1.

有说构造方法的方法名与类名必须一样,父子类不能同名,故不能继,所以不能覆盖构造方法。

这个不用多说,这个例子,就是大神写出来打这样说的人的脸的。

2.

有说因为子类继承父类的时候,先运行父类构造函数;具体的说就是运行父类时就会先“调用”父类的构造函数,注意“调用”和继承不是一个含义,实质上是“自动运行”。

这个强行用中文语法来解释的,达到中文6级了啊。

3.

有说构造方法不是成员函数,故不能继承,所以谈不上覆盖。

这个真的有道理,是java官方文档上的。大多数人找到这里估计就满足了。

但是,跟太阳从东方升起西方落下那样,我想知道为甚么这么设计啊啊啊啊啊啊!!!!!

4.

正确答案

(1).构造器代表这个类本身,在创建之时申请内存。

(2).子类创建的时候,会默认在构造方法的第一行调用父类的默认构造方法-,若修改了必须显示调用。(这就是为什么创建子类时先创建完父类的原因了)

那么很明显了,要是同名类之间可以覆盖了,子类创建时就是创建了两个自己而没有父类。

Java设计的时候,他们绝对想到有些人会像强迫症那样折腾个同名类继承,然后实现构造覆盖的场景吧....

总结

构造方法是唯一的,不能又造爸爸又造儿子

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏积累沉淀

Python快速学习第三天

第三天: 字典 什么是字典? 字典是Python语言中唯一的映射类型。 映射类型对象里哈希值(键,key)和指向的对象(值,value)是一对多的的关系,通常被...

1958
来自专栏积累沉淀

必须掌握的八种排序(1-2)--插入排序,希尔排序

很多人算法和数据结构不好,归根结底就是基础不扎实,算法和数据结构不好的话,达到的高度肯定不会很高,最近重新加强了一下自己的算法基础,决定从最基础的内容开始,如有...

2177
来自专栏牛肉圆粉不加葱

[7] - trait

这是我以前在知乎上看到关于类继承作用的回答,虽不完全正确,却十分明确的表达出了好的代码应避免类继承而尽量使用类组合。Scala 显然也非常赞同这一点,以至于有了...

1072
来自专栏云瓣

读书笔记-你不知道的JavaScript(上)

本文首发在我的个人博客:http://muyunyun.cn/ 《你不知道的JavaScript》系列丛书给出了很多颠覆以往对JavaScript认知的点...

41410
来自专栏偏前端工程师的驿站

一起Polyfill系列:Function.prototype.bind的四个阶段

昨天边参考es5-shim边自己实现Function.prototype.bind,发现有不少以前忽视了的地方,这里就作为一个小总结吧。 一、Function....

1856
来自专栏js编程在工科课程中的简单应用

2.2.1 js基本语法

js不需要像C语言一样显式的指定具体类型,如int,double等,统一使用var关键字声明变量。

1120
来自专栏Java架构师进阶

BATJ架构师常见面试题汇总之一 让你瞬间升华起来

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素...

642
来自专栏女程序员的日常

值类型和引用类型的区别,struct和class的区别

C#值类型和引用类型 1、简单比较   值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中。   值类型(value type):...

2401
来自专栏你不就像风一样

Java性能优化之String字符串优化

Java中八大基本数据类型没有String类型,因为String类型是Java对char数组的进一步封装。

2422
来自专栏carven

浅谈闭包

闭包 – closure, 应该可以说是javascript的一个难点吧, 其实说难也不难, 只是因为没有真正一个权威的人/书去给他一个真正的定义。 不过,学编...

940

扫码关注云+社区

领取腾讯云代金券