Java基础 - 静态块什么时候调用
2018-02-06 本文已影响482人
小乖心塞
在类中用static{},修饰的块被称为静态块。主要用于给静态变量赋值,调用静态方法。在类加载的时候执行一次。
测试方法类
package test;
/**
* chapter1
* Created by wangxun on 2018/2/6上午9:52.
*/
class Test {
public static int X = 100;
public final static int Y = 200;
public Test() {
System.out.println("Test构造函数执行");
}
static {
System.out.println("static语句块执行");
}
public static void display() {
System.out.println("静态方法被执行");
}
public void display_1() {
System.out.println("实例方法被执行");
}
}
public class StaticBlockTest {
public static void main(String args[]) {
try {
Class.forName("test.Test");
Class.forName("test.Test");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
结果
static语句块执行
说明
在main方法中,执行了两次Class.forName
,单就输出了一次static语句块执行
,说明静态块中的代码只在类加载的过程中执行一次。在虚拟机jvm的生命周期中所有的类只会加载一次,而静态块又是伴随类加载而加载。不管你new出多少新的实例,静态块只会加载一次。
静态块什么时候加载呢?
- 调用
Class.forName
的时候。相当于调用Class.forName(className, true, currentLoader)}
,如果将true改为false,表示类不会进行初始化,那么静态块也就不会执行。 - 当new一个类的新的实例的时候。因为new 一个新实例相当于:
Class.forName("").newInstance()
- 调用类的静态方法
Test.display()
- 调用类的静态变量
Teset.X
注意: 调用类的静态常量就不会调用静态块比如:Test.Y
为什么调用静态常量不会进行类加载?
- 如果有个类(A)中包含B类的静态常量,那么编译的时候,会自动将对应的值赋值在其中的class文件中,编译过后,在修改B类对应的常量值。A类因为没有重新编译,那么A类中对应的B类常量值是不会发生变化的。
public class Main {
public static void main(String[] args) {
System.out.println(Node.a);
System.out.println(Node.b);
System.out.println(Node.c);
}
}
class Node {
public static final int a = 10;
public static final int b = (int) (Math.random()*10);
static int c = 30;
}
- 你先javac Main.java 编译, 生成Main.class 和 Node.class 。
- java Main 结果:
bogon:Desktop wangxun$ java Main
10
3
30
- 修改代码
class Node {
public static final int a = 20;
public static final int b = (int) Math.random();
static int c = 40;
}
- 重新 javac Main.java 删除最新的Main.class ,用之前的Main.class 。
- java Main
bogon:Desktop wangxun$ java Main
10
5
40
- a没有发生变化,而b,c都已经发生改变。因为b,c保存的是引用地址,只有当Node进行初始化完成的时候才能确定具体的值,而a就在Main类中直接编译成了对应的值。
static{}语句块的执行次序
1、当一个类中有多个static{}的时候,按照static{}的定义顺序,从前往后执行;
2、先执行完static{}语句块的内容,才会执行调用语句;
示例:
public class TestStatic{
static{
System.out.println(1);
}
static {
System.out.println(2);
}
static {
System.out.println(3);
}
public static void main(String args[]){
System.out.println(5);
}
static {
System.out.println(4);
}
}
结果:程序会输出1,2,3,4,5
3、如果静态变量在定义的时候就赋给了初值(如 static int X=100),那么赋值操作也是在类加载的时候完成的,并且当一个类中既有static{}又有static变量的时候,同样遵循“先定义先执行”的原则;
示例:
class Test{
public static int X=300;
static{
System.out.println(X);
X=200;
System.out.println(X);
}
}
public class StaticBlockTest{
public static void main(String args[]){
System.out.println(Test.X);
}
}
结果:程序会依次输出300,200,200,先执行完X=300,再执行static{}语句块。