属性分为静态属性和非静态属性,参与初始化或者说赋值顺序的,JAVA类的属性的初始化方式有默认初始化,定义时显式初始化,代码块赋值,构造器赋值,spring@value属性注入。为考虑不同的情况,细分为①静态变量默认初始化、②静态变量显式赋值、③非静态代码块赋值、④静态代码块赋值、⑤创建对象、⑥构造器赋值、⑦spring@value属性注入、⑧非静态变量默认初始化、⑨非静态变量显式初始化,此外我们额外插入一个⑤创建对象来对标划分整个过程以便更好理解。现在来一一比较各种方式赋值的先后顺序。
包括 有和没有显式赋值的非静态变量 a和b、有和没有显式赋值的静态变量 c和d、@value属性注入的e、有参和无参构造器、静态和非静态代码块(静态代码块先不启用)。
@Component
class initPriority{
int a = 1;
int b;
static int c;
static int d = 1;
@Value("#{7}")
int e;
public initPriority (){
}
public initPriority (int a, int b, int e){
this.a = a;
this.b = b;
c = b;
d = b;
this.e = e;
}
// {
// a = 3;
// b = 3;
// c = 3;
// d = 3;
// }
// static {
// c = 2;
// d = 2;
// }
}
已加载类但还未创建对象,现在只有静态属性可以调用,理论上现在能执行的初始化方法有静态方法的默认初始化、静态代码块(静态代码块中只能有静态变量)和静态变量的显式初始化。先不启用静态代码块,直接在测试方法中
System.out.println(initPriority.c+","+initPriority.d);//0,1
c是没有显示赋值的,d有显示赋值,默认初始化的0被覆盖了,说明①静态变量默认初始化早于②静态变量显式初始化。
现在把静态代码块的注释去掉,再测试
System.out.println(initPriority.c+","+initPriority.d);//2,2
默认初始化的0和显式赋值的1都被2覆盖了,说明④静态代码块赋值要晚于前面两种初始化方法。
即①静态变量默认初始化 >>> ②静态变量显式初始化 >>> ④静态代码块赋值
对象获取是通过构造器的,对象获取后才有非静态属性,可以肯定,其他的非静态赋值方法一定是晚于创建对象的,但这不意味着构造器赋值紧随其后,对象的创建是一个复杂的过程。
现在我们先不启用非静态代码块,由无参构造得到对象,现在理论上进行的非静态初始化方法只有非静态变量的默认初始化、非静态变量的显式初始化。
initPriority ip1 = new initPriority();
System.out.println(ip1.a+","+ip1.b+","+initPriority.c+","+initPriority.d+","+ip1.e);
//1,0,2,2,0
由于b是没有显示赋值的,a有显示赋值,默认初始化的0被覆盖了,说明⑧非静态变量默认初始化早于⑨非静态变量显式初始化。
现在启用非静态代码块,同样用无参构造,
initPriority ip1 = new initPriority();
System.out.println(ip1.a+","+ip1.b+","+initPriority.c+","+initPriority.d+","+ip1.e);
//3,3,3,3,3
前面的值全部被3覆盖,说明③非静态代码块赋值要晚于⑨和⑩。而且,如果有多个非静态代码块,按代码出现顺序后面的赋值会覆盖前面的。
接下来我们采用有参构造,给所有值赋4,
initPriority ip2 = new initPriority(4,4,4);
System.out.println(ip2.a+","+ip2.b+","+initPriority.c+","+initPriority.d+","+ip2.e);
//4,4,4,4,4
所有值再次被覆盖,所以构造器赋值晚于前面所述的初始化方法,另外,我们知道Spring的属性注入时先获得bean对象再注入的,则⑦spring@value属性注入必然晚于构造器赋值,但是Spring获取对象是通过无参构造获取的,所以两者也没有什么交集。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
initPriority ip3 = context.getBean("initPriority", initPriority.class);
System.out.println(ip3.a+","+ip3.b+","+initPriority.c+","+initPriority.d+","+ip3.e);
//3,3,3,3,7
则①静态变量默认初始化 >>> ②静态变量显式初始化 >>> ④静态代码块赋值 >>> ⑤创建对象 >>> ⑧非静态变量默认初始化 >>> ⑨非静态变量显式初始化 >>> ③非静态代码块赋值 >>> ⑥构造器赋值 >>> ⑦spring@value属性注入。