Java 类成员的初始化顺序

前言:开发中碰到一个Java文件中有很多的成员变量,包括静态和非静态的,还有很多的初始化方法,很好奇这些成员的初始化顺序,在这里作个研究。

 

1  无继承情况下的Java初始化顺序:

class Sample {

Sample(String s)
{

System.out.println(s);

}

Sample()
{

System.out.println("Sample默认构造函数被调用");

}

}

class Test {

static Sample sam=new Sample("静态成员sam初始化");

Sample sam1=new Sample("sam1成员初始化");

static
{

System.out.println("static块执行");

if(sam==null)System.out.println("sam is null");

sam=new Sample("静态块内初始化sam成员变量");

}

Test()
{

System.out.println("Test默认构造函数被调用");

}

 

}

 

//主函数

public
static
void main(String str[])
{

 

Test a=new Test();

 

}

输出结果为:

静态成员sam初始化
-----静态成员初始化

static块执行
-----静态块被执行

静态块内初始化sam成员变量
-----静态块执行

sam1成员初始化
-----普通成员初始化

Test默认构造函数被调用
-----构造函数执行

由此可以得出初始化顺序为:

a 静态成员变量首先初始化(注意,Static可以看做一个静态成员,其执行顺序和其在类中申明的顺序有关)

b 普通成员初始化

c 执行构造函数。

 

对于静态成员(static块可以看成普通的一个静态成员,其并不一定在类初始化时首先执行)和普通成员,其初始化顺序只与其在类定义中的顺序有关,和其他因素无关。

例如下面的例子:

class Test {

static
{

System.out.println("static 块 1 执行");

}

 

static Sample staticSam1=new Sample("静态成员staticSam1初始化");

 

Sample sam1=new Sample("sam1成员初始化");

 

static Sample staticSam2=new Sample("静态成员staticSam2初始化");

 

static
{

System.out.println("static 块 2 执行");

}

 

Test()
{

System.out.println("Test默认构造函数被调用");

}

 

Sample sam2=new Sample("sam2成员初始化");

 

}

则结果为:

static
块
1
执行

静态成员staticSam1初始化

静态成员staticSam2初始化

static
块
2
执行

------------------------------静态成员

sam1成员初始化

sam2成员初始化

------------------------------普通成员

Test默认构造函数被调用

------------------------------构造函数

2 Java继承情况下的初始化顺序:

class Test {

static
{

System.out.println("父类static 块 1 执行");

}

 

static Sample staticSam1=new Sample("父类
静态成员staticSam1初始化");

 

Sample sam1=new Sample("父类 sam1成员初始化");

 

static Sample staticSam2=new Sample("父类
静态成员staticSam2初始化");

 

static
{

System.out.println("父类 static 块 2 执行");

}

 

Test()
{

System.out.println("父类 Test默认构造函数被调用");

}

 

Sample sam2=new Sample("父类 sam2成员初始化");

 

}

 

class TestSub extends Test {

static Sample staticSamSub=new Sample("子类
静态成员staticSamSub初始化");

 

TestSub()
{

System.out.println("子类 TestSub 默认构造函数被调用");

}

 

Sample sam1=new Sample("子类 sam1成员初始化");

 

static Sample staticSamSub1=new Sample("子类
静态成员staticSamSub1初始化");

 

static
{System.out.println("子类 static 块
执行");}

 

Sample sam2=new Sample("子类 sam2成员初始化");

}

执行结果:

父类
static
块
1
执行

父类
静态成员staticSam1初始化

父类
静态成员staticSam2初始化

父类
static
块
2
执行

--------------------------------父类静态成员初始化

子类
静态成员staticSamSub初始化

子类
静态成员staticSamSub1初始化

子类
static
块
执行

--------------------------------子类静态成员初始化

父类 sam1成员初始化

父类 sam2成员初始化

父类 Test默认构造函数被调用

--------------------------------父类普通成员初始化和构造函数执行

子类 sam1成员初始化

子类 sam2成员初始化

子类 TestSub 默认构造函数被调用

--------------------------------父类普通成员初始化和构造函数执行

 

 

由此得出Java初始化顺序为:

a 继承体系的所有静态成员初始化(先父类,后子类)

b父类初始化完成(普通成员的初始化-->构造函数的调用)

c 子类初始化(普通成员-->构造函数)

 

 

Java初始化顺序如图:

 

参考文献:

Java初始化顺序

Java 类成员的初始化顺序的更多相关文章

  1. Java中类成员变量初始化顺序

    一. 定义处默认初始化vs构造函数中初始化 java中类成员变量支持在声明处初始化,也可以在构造函数中初始化,那么这两者有什么区别呢?看下面例子 public class FieldsInit { p ...

  2. Java类的变量初始化顺序

    大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台 ...

  3. java类中元素初始化顺序

    结论:对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器. public class Test4 { @Tes ...

  4. java类及实例初始化顺序

    1.静态变量.静态代码块初始化顺序级别一致,谁在前,就先初始化谁.从上而下初始化(只在类加载时,初始化一次) 2.非静态变量.非静态代码块初始化顺序级别一致,谁在前,就先初始化谁.从上而下初始化(只要 ...

  5. java类对象的初始化顺序

    在下面这个例子中,我们分别在父类和子类中测试了静态代码块.普通代码块.静态成员变量.普通成员变量.构造器.静态内部类. 一:代码块及变量测试 class Field{ public static St ...

  6. c++ 类成员的初始化顺序

    class TestClass1 { public: TestClass1() { cout << "TestClass1()" << endl; } Te ...

  7. java类中元素初始化顺序详解

    父类静态变量父类静态块子类静态变量子类静态块父类普通变量父类普通块父类构造方法子类普通变量子类普通块子类构造方法

  8. java类中成员的初始化顺序(一)

    类被创建之后的成员的初始化顺序到底是怎么样的? 首先 不考虑继承 package com; public class DemoOne { /** * 关于类的初始化顺序 */ //不考虑继承结构的情况 ...

  9. java中的多构造函数以及类字段的初始化顺序

    1.同一个类可以有多个构造函数,多个构造函数之间通过参数来区分.这是方法重载的一个实例.构造函数之间可以相互调用. 2.类的初始化块:可以在类中使用“{”和“}”将语句包围起来,直接将其作为类的成员. ...

随机推荐

  1. oracle where 后面的条件中|| 是什么意思

    oracle where 后面的条件中|| 是连接符号,Oracle中另一个concat函数能够连接两个字符串 concat(a,b) Oracle中nvl函数的使用方法和作用是什么? 假设你某个字段 ...

  2. 关于Android圆形图片的一种优化方案(可以显示网络图片)

    在Android App中,我们经常看到圆形头像图片,然后网上也有很多开源的控件.刚好这个项目用到了,也去找了一些开源的,发现并不完美,所以只好自己优化了,废话不多说,先上效果图: 下面是源码:本人能 ...

  3. 模块化JavaScript设计模式(一)

    在可扩展JavaScript的世界里,假设我们说一个应用程序是模块化(modular)的,那么通常意味着它是由一系列存储于模块中的高度解耦,不同的功能片段组成. 在可能的情况下.通过一处依赖性.松耦合 ...

  4. 云服务器 ECS Linux 系统添加“回收站”

    删除是危险系数很高的操作,一旦误删可能会造成难以估计的损失.在云服务器 ECS Linux 系统中这种危险尤为明显.比如,一条简单的语句:rm –rf /* 就会把整个系统全部删除,而 Linux 并 ...

  5. mkinitrd---简单介绍

    转载:http://blog.csdn.net/zwcq82/article/details/4295481 原来对mkinitrd不是很了解.最近做内核升级,需要制作信息的initrd文件,发现出错 ...

  6. shell shift 使用一例

    这段代码的作用是: 当输入 ./Export.sh 是将当前目录进行打包,当输入./Export.sh XX1 XX2 XX3 .... XXn 时,如果XXn存在,则依次将存在的目录进行打包,打包文 ...

  7. J2EE常用包:

    J2EE常用包: java web开发必掌握的javax.servlet : servlet包及支持javax.servlet.http : http请求支持javax.servlet.jsp : 及 ...

  8. JavaScript中数组操作

    var arr1=new Array(); arr1.push(1);//在数组的中末尾添加元素,并返回新的长度 arr1.push(2);//在数组的中末尾添加元素,并返回新的长度 arr1.pop ...

  9. 控件WebView网页的加载

    Android:控件WebView网页的加载 WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWe ...

  10. 『创意欣赏』30幅逼真的 3D 虚拟现实环境呈现

    又到周末了,给大家分享30幅漂亮的 3D 虚拟现实环境呈现,放松一下.这些创造性的场景都是通过 3D 图形设计软件,结合三维现实环境渲染制作出来的.一起欣赏:) 您可能感兴趣的相关文章 20幅温馨浪漫 ...