概述
下面代码执行的结果name
的结果是多少? 在工作中遇到过类似的问题引发的bug, 故记录一下排查的过程
code
public class Comp {
private String mark = ",";
public Comp(String mark) {
this.mark = mark;
}
private String name = "xx_oo".split(mark)[0];
public static void main(String[] args) {
Comp comp = new Comp("_");
System.out.println(comp.name);
}
}
类似的还有下面这一种
int[] arr = new int[]{1,2,3};
int index = 1;
arr[index++] = arr[index-1]+10 ;
字节码
public com.cache.demo.Comp(java.lang.String);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String ,
7: putfield #3 // Field mark:Ljava/lang/String;
10: aload_0
11: ldc #4 // String xx_oo
13: aload_0
14: getfield #3 // Field mark:Ljava/lang/String;
17: invokevirtual #5 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
20: iconst_0
21: aaload
22: putfield #6 // Field name:Ljava/lang/String;
25: aload_0
26: aload_1
27: putfield #3 // Field mark:Ljava/lang/String;
30: return
从字节码指令来看, 该对象的实例化顺序:
空参数实例化(invokespecial) --> 成员变量的赋值(mark,name) --> 读取有参构造器上方法的值并赋值到当前实例
所以也就不难理解结果为 xx_oo 了, 因为name的赋值操作先于mark的再次赋值, 对指令不了解的可以官网查阅, invokevirtual
执行实例化, invokevirtual
执行实例的方法