使用多态的情况下初始化全过程


在基类的构造器中要尽量避免调用可能被继承重写的方法,否则在初始化时将会引发意外

一个动态绑定的方法调用会深入到继承层次的结构中,它可以调用导出类中的方法,如果在基类的构造器中这样做,就可能会调用某个方法,而这个方法所操纵的成员可能还未进行初始化:

class Glyph{
    void draw(){
        print("Glyph.draw()");   //这个方法其实并未被调用
    }
    Glyph{
        print("Glyph() bfore draw()");
        draw();     //就是在这个地方,调用了可能在导出类中重写的方法,将可能导致意外结果
        print("Glyph() after draw()");
    }
}

class RoundGlyph extends Glyph{
    private int radius = 1;
    RoundGlyph(int r){
        radius = r;
        print("RoundGlyph.RounGlyph(), radius=" + radius);
    }
    void draw(){
        print("RoundGlyph.draw(), radius = "+ radius);   //基类在构造时实际调用的是此方法
    }
}

public class Test(){
    public static void main(String[] args){
        new RoundGlyph(5);      //初始化过程会先调用基类的构造器,基类初始化完成后才会进行导出类的初始化
    }
}

/*
output:
Glyph() before draw()     
RoundGlyph.draw(), radius = 0     //调用了导出类中的方法,但相关参数在子类中,还未初始化
Glyph() after draw()
RoundGlyph.RounGlyph(), radius= 5  //最后才是进行导出类的初始化
*/

在使用继承以及多态时的初始化过程:

1)在任何事件发生之前,将分配给对象的存储空间初始化成二进制的零

2)调用基类构造器。如果此时调用了被重写的方法,用于步骤一的缘故,方法中使用的变量值为0

3)按照声明的顺序调用成员的初始化方法

4)调用导出类的构造器主体

注: 若导出类中的方法通过“组合”方式嵌入了一个类内部的对象的引用,其值就是null

总结:


在编写构造器时,需要尽可能用简单的方法使对象进入正常状态,尽量避免调用其他方法。

在构造器中能够安全调用的只有基类中的final方法(也适用于private方法,它们自动属于final方法)。这些方法不能被覆盖,因此才是安全的。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,746评论 18 399
  • 本章将会介绍 存储属性的初始赋值自定义构造过程默认构造器值类型的构造器代理类的继承和构造过程可失败构造器必要构造器...
    寒桥阅读 778评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,868评论 18 139
  • 1、.java源文件: 一个以”.java“为后缀的源文件:只能有一个与文件名相同的类,可以包含其他类。 2、类方...
    Hughman阅读 1,504评论 1 9
  • 你常问我,生活中为什么有那么多迫不得已。我这里没有具体的答案,只能告诉你,时光短暂,最不能辜负的,是自己。 为某个...
    九月樱桃阅读 179评论 0 0