阿里面试题之变量、代码块、构造器、静态变量,静态代码块的初始化执行顺序讲解

以下为代码部分


public class InitializeDemo {
    private static int k = 1;
    private static InitializeDemo t1 = new InitializeDemo("t1");
    private static InitializeDemo t2 = new InitializeDemo("t2");
    private static int i = print("i");
    private static int n = 99;
    {
        print("初始化块");
        j = 100;
    }
    public InitializeDemo(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "   n=" + n);
        ++i;
        ++n;
    }
    static {
        print("静态块");
        n = 100;
    }
    private int j = print("j");
    public static int print(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "   n=" + n);
        ++n;
        return ++i;
    }
    public static void main(String[] args) {
        InitializeDemo test = new InitializeDemo("test");
    }
}

输出为如下

1:初始化块   i=0   n=0
2:j   i=1   n=1
3:t1   i=2   n=2
4:初始化块   i=3   n=3
5:j   i=4   n=4
6:t2   i=5   n=5
7:i   i=6   n=6
8:静态块   i=7   n=99
9:初始化块   i=8   n=100
10:j   i=9   n=101
11:test   i=10   n=102

Process finished with exit code 0

首先我们要知道,运行一个类

1.首先初始化静态变量和静态代码块(不管以后谁调用这个对象,只会初始化一次):

静态变量的优先级和静态代码块的优先级是一样的.所以谁在谁前面,谁先初始化.我们一般先写变量,之后再写静态代码块,也就是说先运行静态变量的初始化,之后在运行静态代码块的初始化(这样会避免出错===>java: 非法前向引用),如下

static {
        haha=1;//可以赋值

        System.out.println(haha);//但是不能输出,会显示==>java: 非法前向引用
}
private static int haha;

2.之后初始化变量和代码块,再之后在初始化构造器:

变量和代码块的优先级是一样的(谁在前,谁先初始化),但优先于构造器的初始化.也就是说,构造器不管在哪里,都是最后被初始化的.因为他们不是静态的,所以他们存在于对象里面,new一个对象就会被初始化一次.

以下是基本数据类型的初始化零值:(来自《深入了解java虚拟机》7.3.3章节中的表7-1)

intbyteshortlongbooleanfloatdoublecharreference
0(byte)0(short)00Lfalse0.0f0.0d'\u0000'null

那么,上述代码流程示例为

  1. 首先给k赋值1
  2. 然后new对象t1
    1. 先执行初始化块
    2. 执行private int j = print("j");
    3. 执行构造器
  3. 继续new对象t2
    1. 先执行初始化块
    2. 执行private int j = print("j");
    3. 执行构造器
  4. 执行private static int i = print("i");
  5. 给n赋值99
  6. 执行静态块
  7. 执行main方法
    1. new对象test
      1. 先执行初始化块
      2. 执行private int j = print("j");
      3. 执行构造器

看懵了是吧,那我们继续往底层深挖

接下来我们根据反编译分析

我们反编译一下该字节码文件,执行代码如下

javap -c InitializeDemo.class

我们会得到如下源码

public class com.heaboy.mvc.InitializeDemo {
  public com.heaboy.mvc.InitializeDemo(java.lang.String);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: ldc           #2                  // String 初始化块
       6: invokestatic  #3                  // Method print:(Ljava/lang/String;)I
       9: pop
      10: aload_0
      11: bipush        100
      13: putfield      #4                  // Field j:I
      16: aload_0
      17: ldc           #5                  // String j
      19: invokestatic  #3                  // Method print:(Ljava/lang/String;)I
      22: putfield      #4                  // Field j:I
      25: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      28: new           #7                  // class java/lang/StringBuilder
      31: dup
      32: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
      35: getstatic     #9                  // Field k:I
      38: dup
      39: iconst_1
      40: iadd
      41: putstatic     #9                  // Field k:I
      44: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      47: ldc           #11                 // String :
      49: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      52: aload_1
      53: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      56: ldc           #13                 // String    i=
      58: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      61: getstatic     #14                 // Field i:I
      64: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      67: ldc           #15                 // String    n=
      69: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      72: getstatic     #16                 // Field n:I
      75: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      78: invokevirtual #17                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      81: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      84: getstatic     #14                 // Field i:I
      87: iconst_1
      88: iadd
      89: putstatic     #14                 // Field i:I
      92: getstatic     #16                 // Field n:I
      95: iconst_1
      96: iadd
      97: putstatic     #16                 // Field n:I
     100: return

  public static int print(java.lang.String);
    Code:
       0: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: new           #7                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
      10: getstatic     #9                  // Field k:I
      13: dup
      14: iconst_1
      15: iadd
      16: putstatic     #9                  // Field k:I
      19: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      22: ldc           #11                 // String :
      24: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: aload_0
      28: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: ldc           #13                 // String    i=
      33: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      36: getstatic     #14                 // Field i:I
      39: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      42: ldc           #15                 // String    n=
      44: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      47: getstatic     #16                 // Field n:I
      50: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      53: invokevirtual #17                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      56: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      59: getstatic     #16                 // Field n:I
      62: iconst_1
      63: iadd
      64: putstatic     #16                 // Field n:I
      67: getstatic     #14                 // Field i:I
      70: iconst_1
      71: iadd
      72: dup
      73: putstatic     #14                 // Field i:I
      76: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: new           #19                 // class com/heaboy/mvc/InitializeDemo
       3: dup
       4: ldc           #20                 // String test
       6: invokespecial #21                 // Method "<init>":(Ljava/lang/String;)V
       9: astore_1
      10: return

  static {};
    Code:
       0: iconst_1
       1: putstatic     #9                  // Field k:I
       4: new           #19                 // class com/heaboy/mvc/InitializeDemo
       7: dup
       8: ldc           #22                 // String t1
      10: invokespecial #21                 // Method "<init>":(Ljava/lang/String;)V
      13: putstatic     #23                 // Field t1:Lcom/heaboy/mvc/InitializeDemo;
      16: new           #19                 // class com/heaboy/mvc/InitializeDemo
      19: dup
      20: ldc           #24                 // String t2
      22: invokespecial #21                 // Method "<init>":(Ljava/lang/String;)V
      25: putstatic     #25                 // Field t2:Lcom/heaboy/mvc/InitializeDemo;
      28: ldc           #26                 // String i
      30: invokestatic  #3                  // Method print:(Ljava/lang/String;)I
      33: putstatic     #14                 // Field i:I
      36: bipush        99
      38: putstatic     #16                 // Field n:I
      41: ldc           #27                 // String 静态块
      43: invokestatic  #3                  // Method print:(Ljava/lang/String;)I
      46: pop
      47: bipush        100
      49: putstatic     #16                 // Field n:I
      52: return

从上可以看出:

我们首先运行的是static静态修饰的变量代码块,然后是主方法,之后是非静态变量和非静态代码块和构造器

    private static int k = 1;// Field k:I
    private static InitializeDemo t1 = new InitializeDemo("t1"); // String t1, Method "<init>":(Ljava/lang/String;)V
    private static InitializeDemo t2 = new InitializeDemo("t2"); // String t2, Method "<init>":(Ljava/lang/String;)V
    private static int i = print("i");// String i, Method print:(Ljava/lang/String;)I
    private static int n = 99;// Field n:I

    static {// String 静态块
        print("静态块");
        n = 100;
    }

    public static int print(String str) {// Method print:(Ljava/lang/String;)I,被调用的时候使用
        System.out.println((k++) + ":" + str + "   i=" + i + "   n=" + n);
        ++n;
        return ++i;
    }

之后是main方法

 public static void main(String[] args) {
        InitializeDemo test = new InitializeDemo("test");
    }

程序到此结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值