在類中用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{}語句塊。