Java——对象初始化顺序使用详解

一、 代码块的概念

在探究对象初始化顺序之前,我们先通过代码来了解一下代码块的概念。

class Test{
  public static String str1; //静态字段

  public String str2;     //普通字段

  static{
    //静态代码块
  }

  {
    //构造代码块
  }

  public Test() {
    //构造函数
  }
}

二、 创建子类对象时,对象的初始化顺序

1. 字段初始化、代码块和构造函数的执行顺序

我们先看代码和结果

public class CodeBlockTest {
  public static void main(String[] args) {
    Child child = new Child();
  }
}
class Father {
  public static String fatherStr1 = "fatherStr1(静态字段初始化值)";

  public String fatherStr2 = "fatherStr2(字段初始化值)";
  static {
    System.out.println("父类静态代码块:" + fatherStr1);
    fatherStr1 = "fatherStr1(静态代码块赋值)";
  }
  {
    System.out.println("父类构造代码块:" + fatherStr2);
    fatherStr2 = "fatherStr2(构造代码块赋值)";
  }
  public Father() {
    System.out.println("父类构造函数块:" + fatherStr2);
    fatherStr2 = "fatherStr2(构造函数赋值)";
  }
}
class Child extends Father {
  public static String childStr1 = "childStr1(静态字段初始化值)";
  public String childStr2 = "childStr2(字段初始化值)";
  static {
    System.out.println("子类静态代码块:" + childStr1);
    childStr1 = "childStr1(静态代码块赋值)";
  }
  {
    System.out.println("子类构造代码块:" + childStr2);
    childStr2 = "childStr2(构造代码块赋值)";
  }
  public Child() {
    System.out.println("子类构造函数:" + childStr2);
    childStr2 = "childStr2(构造函数赋值)";
  }
}
//  输出结果:
//  父类静态代码块:fatherStr1(静态字段初始化值)
//  子类静态代码块:childStr1(静态字段初始化值)
//  父类构造代码块:fatherStr2(字段初始化值)
//  父类构造函数块:fatherStr2(构造代码块赋值)
//  子类构造代码块:childStr2(字段初始化值)
//  子类构造函数:childStr2(构造代码块赋值)

通过每执行一个代码块或构造函数,输出字段在上一代码块执行后的值,以此来探究对象的初始化顺序。

由目前的输出结果可知,对于对象的初始化顺序,我们可以得出以下结论:

1. 父类静态字段初始化

2. 父类静态代码块、子类静态字段初始化 (接下来探究两者的顺序)

3. 子类静态代码块

4. 父类普通字段初始化

5. 父类构造代码块

6. 父类构造函数

7. 子类普通字段初始化

8. 子类构造代码块

9. 子类构造函数

2. 父类静态代码块和子类静态字段初始化的执行顺序

还是一样,我们通过代码的执行结果来探究两者间的执行顺序。

public class CodeBloacTest2 {
  public static void main(String[] args) {
    Child child = new Child();
  }
}
class Father {
  public static String fatherStr = "(静态字段初始化值)";
  static {
    System.out.println("父类静态代码块:fatherStr" + fatherStr);
    fatherStr = "(静态代码块赋值)";
  }
}
class Child extends Father {
  public static String childStr = fatherStr;
  static {
    System.out.println("子类静态代码块:childStr = fatherStr" + childStr);
    childStr = "(静态代码块赋值)";
  }
}
//  输出结果:
//  父类静态代码块:fatherStr(静态字段初始化值)
//  子类静态代码块:childStr = fatherStr(静态代码块赋值)

我们在子类静态字段childStr初始化的时候,赋的是父类静态字段fatherStr的值。由输出结果可知,childStr初始化后的值是父类静态代码块执行后赋予fatherStr的值。由此可知两者的执行顺序为:父类静态代码块==>子类静态字段初始化

三、 结论

父类静态字段初始化

父类静态代码块

子类静态字段初始化

子类静态代码块

父类普通字段初始化

父类构造代码块

父类构造函数

子类普通字段初始化

子类构造代码块

子类构造函数

通过结论我们可以很明显的看出:static字段、代码块的执行顺序优先于非static字段、代码块。这是因为在静态域是属于类的,在类加载后就一直存在;而普通域需要创建对象才能访问。而在创建对象时,需要先加载父类,然后再加载子类,因此父类的静态字段初始化和静态代码块执行先于子类。

以上内容希望对各位朋友有所帮助

(0)

相关推荐

  • 通过java字节码分析学习对象初始化顺序

    复制代码 代码如下: mockery.checking(new Expectations() { {               one(new Object()).toString();               will(returnValue(""));           }       }); 下面写一个写一个简单的类演示这个例子 复制代码 代码如下: public class Test { int i = 1;    {        int j = 1;       

  • java对象初始化顺序验证示例

    复制代码 代码如下: public class Derive extends Base {    private Member m1 = new Member("Member 1");    {        System.out.println("Initial Block()");    } public Derive() {        System.out.println("Derive()");    } private Member

  • Java对象初始化顺序的使用

    单一类:(静态成员变量&静态初始化块)<(成员变量&初始化块)<构造函数 复制代码 代码如下: public class 对象初始化顺序 {    public static void main(String[] args){        Person p = new Person();    }}class Person{    public static String staticfield ="静态成员变量";    public String fi

  • Java中对象初始化顺序的详细介绍

    前言 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.最近我发现了一个有趣的问题,这个问题的答案乍一看下骗过了我的眼睛.看一下这三个类: package com.ds.test; public class Upper { String upperString; public Upper() { Initializer.initialize(this); } } package com.ds.test; public class Lower extends

  • Java——对象初始化顺序使用详解

    一. 代码块的概念 在探究对象初始化顺序之前,我们先通过代码来了解一下代码块的概念. class Test{ public static String str1; //静态字段 public String str2; //普通字段 static{ //静态代码块 } { //构造代码块 } public Test() { //构造函数 } } 二. 创建子类对象时,对象的初始化顺序 1. 字段初始化.代码块和构造函数的执行顺序 我们先看代码和结果 public class CodeBlockTe

  • java存储以及java对象创建的流程(详解)

    java存储: 1)寄存器:这是最快的存储区,位于处理器的内部.但是寄存器的数量有限,所以寄存器根据需求进行分配.我们不能直接进行操作. 2)堆栈:位于通用RAM中,可以通过堆栈指针从处理器那里获取直接支持.堆栈指针往下移动,则分配新的内存.网上移动,则释放内存.但是 在创建程序的时候必须知道存储在堆栈中的所有项的具体生命周期,以便上下的移动指针.一般存储基本类型和java对象引用. 3)堆:位于通用RAM中,存放所有的java对象,不需要知道具体的生命周期. 4)常量存储:常量值通常直接存放在

  • C++ 成员变量的初始化顺序问题详解

    C++ 成员变量的初始化顺序问题详解 问题来源: 由于面试题中,考官出了一道简单的程序输出结果值的题:如下, class A { private: int n1; int n2; public: A():n2(0),n1(n2+2){} void Print(){ cout << "n1:" << n1 << ", n2: " << n2 <<endl; } }; int main() { A a; a.P

  • Java对象类型的判断详解

    instanceof 判断某个对象是否是某个类的实例或者某个类的子类的实例.它的判断方式大概是这样的: public<T> boolean function(Object obj, Class<T> calzz) { if (obj == null) { return false; } try { T t = (T) obj; return true; } catch (ClassCastException e) { return false; } } Class.equals()

  • Java对象Serializable接口实现详解

    这篇文章主要介绍了Java对象Serializable接口实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 导读 最近这段时间一直在忙着编写Java业务代码,麻木地搬着Ctrl-C.Ctrl-V的砖,在不知道重复了多少次定义Java实体对象时"implements Serializable"的C/V大法后,脑海中突然冒出一个思维(A):问了自己一句"Java实体对象为什么一定要实现Serializable接口呢?&qu

  • Java类继承关系中的初始化顺序实例详解

    本文实例讲述了Java类继承关系中的初始化顺序.分享给大家供大家参考,具体如下: Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类InitialOrderWithoutExtend中包含了静态成员变量(类变量)SampleClass 类的一个实例,普通成员变量SampleClass 类的2个实例(在程序中的顺序不一样)以及一个静态代码块,其中静态代码块

  • Java中JSON字符串与java对象的互换实例详解

    在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好,下面先看下JSON的格式, JSON可以有两种格式,一种是对象格式的,另一种是数组对象, {"name":"JSON","address":"北京市西城区","age":25}//JSON的对象格式的字符串 [

  • 手写redis@Cacheable注解 参数java对象作为key值详解

    目录 1.实现方式说明 1.1问题说明 1.2实现步骤 2.源代码 3.测试 1.实现方式说明 本文在---- 手写redis @ Cacheable注解支持过期时间设置   的基础之上进行扩展. 1.1问题说明 @ Cacheable(key = “'leader'+#p0 +#p1 +#p2” )一般用法,#p0表示方法的第一个参数,#p1表示第二个参数,以此类推. 目前方法的第一个参数为Java的对象,但是原注解只支持Java的的基本数据类型. 1.2实现步骤 1.在原注解中加入新的参数,

  • 如何将Java对象转换为JSON实例详解

    要将 Java 对象或 POJO (普通旧 Java 对象)转换为 JSON,我们可以使用JSONObject将对象作为参数的构造函数之一.在下面的示例中,我们将StudentPOJO 转换为 JSON 字符串.Student类必须提供 getter 方法,JSONObject通过调用这些方法创建 JSON 字符串. 在此代码段中,我们执行以下操作: 使用 setter 方法创建Student对象并设置其属性. 创建JSONObject调用object并将Student对象用作其构造函数的参数.

随机推荐