文档章节

对象初始化流程

hc24
 hc24
发布于 2017/01/26 22:11
字数 1263
阅读 15
收藏 1

我们根据一段代码来分析对象初始化流程:

/**

 *基类

 */

class Base{

    public static int a = 10;

    public int b;

    static

    {

        System.out.println("Static Init Base " + a);

    }

    public Base()

    {

        System.out.println("Init Base " + this.b);

        b = 30;

        System.out.println("Init Base B After Base()" + this.b);

    }

    public static int c = getC();

        

    public static int getC(){

        System.out.println("Init Base C 100");

        return 100;

    }

    static

    {

        System.out.println("Static Init Base DOWNC");

    }

    public static int d = getD();

    

    public static int getD(){

        System.out.println("Init Base D 200");

        return 200;

    }

}

/**

 *一级子类

 **/

class SuperClass extends Base{

    public static int a1 = getSuperStaticNumber();

    public int b1 = getSuperInstanceNumber();

    public SuperClass()

    {

        System.out.println("Init SuperClass" + this.b1);

    }

    static

    {

        System.out.println("Static Init SuperClass" + a1);

    }

    public static int getSuperStaticNumber()

    {

        System.out.println("Static member init");

        return 100;

    }

    public int getSuperInstanceNumber()

    {

        System.out.println("Instance member init");

        return 200;

    }

}

/**

 *二级子类为测试该代码的驱动类

 */

public class SubClass extends SuperClass{

    public static int a2 = getStaticNumber();

    public int b2 = getInstanceNumber();

    public SubClass()

    {

        System.out.println("Init SubClass " + this.b2);

    }

    public static int getStaticNumber()

    {

        System.out.println("Static member init Sub");

        return 1000;

    }

    public int getInstanceNumber()

    {

        System.out.println("Instance member init Sub");

        return 2000;

    }

    public static void main(String args[])

    {

        new SubClass();

    }

    static

    {

        System.out.println("Static Init " + a2);    }

}  

这段代码会有以下输出:

Static Init Base 10

Init Base C 100

Static Init Base DOWNC

Init Base D 200

Static member init

Static Init SuperClass100

Static member init Sub

Static Init 1000

Init Base 0

Init Base B After Base()30

Instance member init

Init SuperClass200

Instance member init Sub

Init SubClass 2000  

 

1、类加载:

[1]对象在初始化过程,JVM会先去搜索该类的顶级父类,直到搜索到我们所定义的SubClass继承树上直接继承于Object类的子类,在这里就是Base类;

  [2]然后JVM会先加载Base类,然后初始化Base类的静态变量静态初始化块,静态变量和静态初始化块初始化的顺序,按照代码书写从上到下的顺序。按照这样第一句话会输出:Static Init Base 10【*:此时该类还未调用构造函数,构造函数是实例化的时候调用的】

  [3]然后JVM按照继承树往下搜索,继续加载Base类的子类,直到加载完我们使用的对象所在的类。

2、实例化:

  [4]类加载完了过后开始对类进行实例化操作,这个过程还是会先搜索到直接继承于Object类的子类,在这里就是Base类;

  [5]JVM会实例化Base类的成员变量,然后调用Base类的构造函数;

  [6]之后,JVM会递归往继承树下边进行调用,顺序还是遵循:成员变量->构造函数

  [7]最后直到SubClass类的构造函数调用完成

  按照上边书写的逻辑,我们就很清楚了上边源代码的执行结果,而整个JVM初始化某个类的流程就是按照以上逻辑进行

  在构造函数调用过程,有几点是需要我们留意的,这里就不提供代码实例,有兴趣的朋友可以自己去试试

  [1]如果一个类的父类没有无参数构造函数,也就是说父类自定义了一个带参数的构造函数,那么系统不会提供无参数构造函数,此时子类在调用构造函数的时候必须最开始显示调用super(param),因为在构造函数调用之前系统总会先去调用父类的构造函数

  [2]若一个类定义的时候没有提供构造函数,JVM会自动为该类定义一个无参数的构造函数

  [3]一个类在调用构造函数的时候,JVM隐藏了一句代码super(),前提是父类未定义构造函数或者显示定义了无参构造函数;其含义就是调用父类的构造函数,如果父类的无参数构造函数被覆盖的话需要在子类构造函数中显示调用父类带参数的构造函数

[4]当类中的成员函数遇到变量的时候,会先根据变量名在函数域即局部变量范围内去寻找该变量,如果找不到才会去寻找实例变量或者静态变量,其意思可以理解为局部变量可以和实例变量或者静态变量同名,而且会在函数调用过程优先使用,这个原因在于在函数范围内,如果调用的变量是实例变量,其中前缀this.被隐藏了。

[5]java中,在使用new操作符创建一个类的实例对象的时候,实例变量会首先执行缺省初始化,即会被初始化成近零的值(如整形赋值0,字符串赋值null),如果有对成员变量赋初值,则对成员变量进行赋值,然后再进入类的构造函数。

[6]在构造函数里面,首先要检查是否有this或者super调用,this调用是完成类本身的构造函数之间的调用,super调用是完成对父类的调用。二者只能出现一个,并且只能作为构造函数的第一句出现。在调用this和super的时候实现跳转,转而执行被调用的this构造函数或者super构造函数。

 

© 著作权归作者所有

hc24
粉丝 5
博文 35
码字总数 16991
作品 0
成都
程序员
私信 提问
ReactiveCocoa - Swift 解读系列三:SignalProducer的实现原理和使用

是RAS对的封装。之前我们使用的时候,我们会先定义一个信号,并获取它的发送器,然后给信号添加相应的观察者,最后通过发送器发送信号内容,观察者则可以收到信号并执行预设的函数体。从这个...

BennyLoo
2017/11/20
0
0
六月/SilverSpi

SPI框架 本项目工程主要是实现了一个spi的使用框架,借此可以方便的利用spi的思想,实现一些业务场景的区分 设计思路 下图围绕 为中心,描述了三个主要的流程: load所有的spi实现 初始化选择...

六月
2017/07/30
0
0
Mybatis3.3.x技术内幕(八):Mybatis初始化流程(上)

Mybatis初始化流程,其实就是组装重量级All-In-One对象Configuration的过程,主要分为系统环境参数初始化和Mapper映射初始化,其中Mapper映射初始化尤为重要。 inputStream = Resources.getR...

祖大俊
2016/05/02
2.8K
2
浅析微信小程序 App() 和 Page() 函数的内部实现

在小程序开发中, 和 是我们最熟悉也是最常用的两个函数,今天我们就来分析一下它们的内部实现,以及调用时的初始化流程。 前一段时间,我们公众号转载了有赞技术团队的《从源码看微信小程序...

a独家记忆
2018/07/11
0
0
Spring 源码(十一)Spring流程汇总

Spring 容器初始化流程 Spring 容器初始化流程大致流程如下: this():注册内置的BeanPostProcessor的BeanDefinition到容器 register(annotatedClasses):注册配置类 BeanDefinition 到容器 ...

xiaolyuh
10/06
74
3

没有更多内容

加载失败,请刷新页面

加载更多

关于运维,该怎么决定它的方向,这个似工作又似兴趣的存在

我之前主要从事网络、桌面、机房管理等相关工作,这些工作使我迷惘,这应该是大多数运维人都经历过的过程; 18年国庆,我从国内前三的消费金融公司裸辞,下海创业,就是想要摆脱这样的困境。...

网络小虾米
30分钟前
5
0
Java Timer的用法

Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("11232"); } }, 200000 , 1000); public void schedule(TimerTask task, long delay......

林词
33分钟前
5
0
使用js动态加载外部js文件以及动态创建script脚本

动态脚本指的是在页面加载时不存在,但将来的某一时刻通过修改该DOM动态添加的脚本。和操作HTML元素一样,创建动态脚本也有两种方式:插入外部文件和直接插入JavaScript代码。 动态加载外的外...

Bing309
41分钟前
3
0
从零开始入门 K8s | Kubernetes 网络概念及策略控制

作者 | 阿里巴巴高级技术专家 叶磊 一、Kubernetes 基本网络模型 本文来介绍一下 Kubernetes 对网络模型的一些想法。大家知道 Kubernetes 对于网络具体实现方案,没有什么限制,也没有给出特...

阿里巴巴云原生
45分钟前
3
0
天气获取

本文转载于:专业的前端网站➨天气获取 $.get("http://wthrcdn.etouch.cn/WeatherApi", { citykey: cityCode }, function (d) { //创建文档对象 var parser = new ......

前端老手
45分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部