static静态变量和静态代码块的执⾏顺序
众所周知在android中static 修饰的会被称之为静态常量,静态变量,静态⽅法,还有就是静态代码块,⽤static{ // 代码块⾮static修饰的⽅法,变量,常量,是不能再静态代码块中使⽤的 } 表⽰。
static修饰的是跟着类⾛的,⽽不是跟随对象,这个⼤家都是知道的。那么⼤家是否知道它们之间的运⾏顺序的关系呢?今天,我就给⼤家简单讲解⼀下吧。
静态常量,静态变量,静态⽅法,⼤家都知道是通过类名直接调⽤的(例如:Static() )。但是静态代码块⼤家都没有主动调⽤过对吧。那它到底什么时候被执⾏呢?让我来揭晓吧,其实只要你的代码在任意地⽅,动⽤了静态代码块所属的类中的任意东西,那么该静态代码块就会马上执⾏(说⽩了就是静态代码块是这个类最先执⾏的代码,但前提是你要使⽤这个类,不使⽤的话,这个类中的静态代码块是不会执⾏的与静态变量相⽐就是看代码编写的前后顺序,和静态⽅法有很⼤的区别)。当⼀个类中有多个静态代码块的时候,是按照代码编写的上下顺序先后执⾏的。
静态代码块与静态变量之间的关系:
如果你想正确使⽤两者的话,个⼈建议你必须把静态变量定义在静态代码块的前⾯,因为两个的执⾏是会根据代码编写的顺序来决定的。这个⽐较难理解,我来举个例⼦吧,情况下⾯代码:
public class Demo{
public static int i;
static{
i = 20;
//这⾥的i,是可以被⽤作运算的。
}
}
这时候如果你在main函数输出i,那么i=20;
public class Demo{
static{
i = 20;
/
/这⾥的i,是不能被⽤作运算的,因为本质上 i 还未被定义
}
public static int i;
}
这时候如果你在main函数输出i,那么i=20;
public class Demo{
static{
i = 20;
//这⾥的i,是不能被⽤作运算的,因为本质上 i 还未被定义
}
public static int i = 1;
}
//但是如果我们给静态的i附上⼀个初始值后,那么结果就变了。
这时候如果你在main函数输出i,那么i=1;
上述的代码就其实就是进⼀步说明静态变量和static修改的静态代码块运⾏的顺序是根据代码编写的先后,⽽且第⼆种写法毫⽆意义。未了避免出现不必要的⿇烦,本⼈强制建议,不管是否有在静态代码块中使⽤静态变量,都应当把静态变量写在静态代码块的上⽅。静态常量的情况和静态变量是⼀样,这⾥就不在做说明了。
1、执⾏顺序
1.1、⼀个类中的初始化顺序
类内容(静态变量、静态初始化块) => 实例内容(变量、初始化块、构造器)
1.2、两个具有继承关系类的初始化顺序
⽗类的(静态变量、静态初始化块)=> ⼦类的(静态变量、静态初始化块)=> ⽗类的(变量、初始化块、构造器)=> ⼦类的(变量、初始化块、构造器)
⽰例如下:(结果见注释)
1 class A {
2 public A() {
3 System.out.println("Constructor A.");
4 }
5
6 {
7 System.out.println("Instance Block A.");
8 }
9 static {
10 System.out.println("Static Block A.");
11 }
12
13 public static void main(String[] args) {
14 new A();/*
15 * Static Block A. Instance Block A. Constructor A.
16 */
17 }
18 }
19
20 class B extends A {
21 public B() {
22 System.out.println("Constructor B.");
23 }
24
25 {
26 System.out.println("Instance Block B.");
27 }
28 static {
29 System.out.println("Static Block B.");
30 }
31
32 public static void main(String[] args) {
33 new A();/*
34 * Static Block A. Static Block B. Instance Block A. Constructor A.
35 */
36 System.out.println();
37 new B();/*
38 * Instance Block A. Constructor A. Instance Block B. Constructor B.
39 */// 静态成员和静态初始化块只会执⾏⼀次。
40 }
41 }
2、对变量值的影响
⼀个变量,若显⽰初始化、初始化块对该变量赋值、构造⽅法对该变量赋值同时存在,则变量最终值如何确定?按1节中所述的执⾏顺序确定。
这⾥考虑初始化块在变量定义之前的情形,此时会造成迷惑。
初始化块可以对在它之后定义的变量赋值,但不能访问(如打印)。如:
1 static {
2 a = 3;
3 // int b=a;//Cannot reference a field before it is defined
4 // System.out.println(a);//Cannot reference a field before it is defined
5 }
6 static int a = 1;
“对变量值的影响”是指对变量赋值的初始化块位于变量定义之前时,变量的最终值根据变量定义时是否显⽰初始化⽽会有不同结果(若初始化块位于变量定义之后,那么变量的值显然很容易就确定了,不会造成迷惑)。如:
1 class Test {
2 static {
3 a = 3;
4 // int b=a;//Cannot reference a field before it is defined
5 // System.out.println(a);//Cannot reference a field before it is defined
6 b = 3;
7 }
8 static int a = 1;
9 static int b;
10
11 public static void main(String[] args) {
12 System.out.println(a);//1
13 System.out.println(b);//3
14 }
15 }
判断⽅法:
显⽰初始化内部隐含定义变量和对变量进⾏赋值的初始化块两部分,所以初始化块和显⽰初始化哪个在后变量的最终值就是该值。
更多⽰例:
1:
1 class C {
2
3 static {
4 a = 2;
5 b = 2;
6 }
7 static int a;
8 static int b = 1;
9
10 public C() {
11 e = 3;
12 }
13
14 {
15 c = 2;
16 d = 2;
17 e = 2;
18 }
19 int c;
20 int d = 1;
21 int e = 1;
22
23 public static void main(String[] args) {
24 System.out.println(C.a);//2
25 System.out.println(C.b);//1
26 System.out.println(new C().c);//2
27 System.out.println(new C().d);//1
28 System.out.println(new C().e);//3
29 }
2:
1 class C {
2 public C() {
3 }
4
5 {
6 a = 3;
7 }
8 static {
9 a = 2;
10 }
11 static int a;
12 static int b;
13
14 public static void main(String[] args) {
15 System.out.println(C.a);// 2
16 System.out.println(new C().a);// 3
17 System.out.println(C.b);// 0
18 }
19 }
3:
1 class C {
2 // 以下关于静态初始化的
3 static {
4 a = 2;
5 }
6 static int a = 1;
7 static int b = 1;
8 static {
9 b = 2;
10 c = 2;
11 }
12 static int c;
13
14 {
15 d = 2;
16 }
17 int d = 1;
18 int e = 1;
19 {
20 e = 2;
21 f = 2;
22 }
23 int f;
24
25 public static void main(String[] args) {
26 System.out.println(C.a);// 1
27 System.out.println(C.b);// 2
28 System.out.println(new C().c);// 2
29 System.out.println(new C().d);// 1
30 System.out.println(new C().e);// 2
31 System.out.println(new C().f);// 2
32 }
33 }static修饰的变量
3、总结
执⾏顺序:
1、类内容(静态变量、静态初始化块) => 实例内容(变量、初始化块、构造器)
2、⽗类的(静态变量、静态初始化块)=> ⼦类的(静态变量、静态初始化块)=> ⽗类的(变量、初始化块、构造器)=> ⼦类的(变量、初始化块、构造器)
初始化块可以对在它之后定义的变量赋值,但不能访问(如打印)。
变量最终值:⼀个变量,若显⽰初始化、初始化块对该变量赋值、构造⽅法对该变量赋值同时存在,则变量最终值如何确定:
1、按执⾏顺序
2、若对变量赋值的初始化块在变量定义前时:若变量显⽰初始化了则最终为显⽰初始化值,否则为初
始化块的赋值。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论