Java类数据域初始化顺序

Java类中数据域初始化顺序

在《Java核心技术:卷一》中,对于初始化数据域的初始化次序,有以下说明:

  1. 所有数据域都被初始化为默认值
  2. 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块
  3. 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体
  4. 执行这个构造器的主体。
    对于静态域的初始化过程:
  5. 在类的第一次加载时,将静态域初始化为默认值
  6. 所有的静态初始化语句以及静态初始化块都依照类定义的顺序执行。
    然而,Java类中数据域为什么是按照上面所说的步骤进行的呢?以下从JVM的角度来分析这个问题。
    首先看静态域的初始化过程:
public class Demo{
    static int i=10;
    static{
        i=20;
    }
    static{
        i=30;
    }
}

我们将上面代码的字节码反编译后得到以下结果,会发现编译器会按上至下,收集所有static静态代码和静态成员赋值的代码,合并成一个特殊的方法()V

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        10
         2: putstatic     #2                  // Field i:I
         5: bipush        20
         7: putstatic     #2                  // Field i:I
        10: bipush        30
        12: putstatic     #2                  // Field i:I
        15: return
      LineNumberTable:
        line 2: 0
        line 5: 5
        line 8: 10
        line 9: 15
}

接下来我们看非静态变量初始化过程:

public class Demo{
    private String a=“s1”;
    {
        b=20;
    }
    private int b=20;
    {
        a=“s2”;
    }
    public Demo(String a, int b){
        this.a=a;
        this.b=b;
    }
    public static void main(String[] args) {
        Demo d=new Demo(“s3”, 30);
        System.out.println(d.a);
        System.out.println(d.b);
    }
}

上面代码的字节码经过反编译后,得到以下结果,我们会发现编译器按从上到下的顺序,收集所有代码和成员变量复制的代码,形成新的构造方法,但原始构造方法会被放在最后,如下图28-35的内容

public Demo(java.lang.String, int);
    descriptor: (Ljava/lang/String;I)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String s1
         7: putfield      #3                  // Field a:Ljava/lang/String;
        10: aload_0
        11: bipush        20
        13: putfield      #4                  // Field b:I
        16: aload_0
        17: bipush        20
        19: putfield      #4                  // Field b:I
        22: aload_0	
        23: ldc           #5                  // String s2
        25: putfield      #3                  // Field a:Ljava/lang/String;
        28: aload_0								 //-----------------------------------
        29: aload_1
        30: putfield      #3                  // Field a:Ljava/lang/String;
        33: aload_0
        34: iload_2
        35: putfield      #4                  // Field b:I-------------------------
        38: return
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值