1.請先看Demo:
class Initable1Parent {
static {
System.out.println("Initializing Initable1Parent...");
}
}
class Initable2Parent {
static {
System.out.println("Initializing Initable2Parent...");
}
}
class Initable1 extends Initable1Parent{
static {
System.out.println("Initializing Initable1...");
}
}
class Initable2 extends Initable2Parent{
static {
System.out.println("Initializing Initable2...");
}
}
public class InitializeDemo {
@Test
public void test01() throws Exception {
//使用.class方式加載位元組碼
Class initable1Clazz = Initable1.class;
//使用Class.forName(String className)方式加載位元組碼
Class initable2Clazz = Class.forName("com.tca.thinkInJava.chap14.test.Initable2");
}
}
執行結果:
Initializing Initable2Parent...
Initializing Initable2...
可以看出:
使用.class方式加載類并沒有對該類及其父類進行靜态初始化(并沒有執行Initable1Parent和Initable1的靜态代碼塊),但是使用Class.forName(String className)方式則對該類和父類進行了靜态初始化。
2. 再看Demo
class Mouse {
public static final String type = "Mouse";
static {
System.out.println("Initializing Mouse...");
}
}
class Cat {
public static String type = "Cat";
static {
System.out.println("Initializing Cat...");
}
}
public class InitializeDemo {
@Test
public void test02() {
Class dogClazz = Mouse.class;
System.out.println(Mouse.type);
Class catClazz = Cat.class;
System.out.println(Cat.type);
}
}
執行結果:
Mouse
Initializing Cat...
Cat
可以看出:
1. 使用.class方式加載位元組碼時,并沒有對類進行靜态初始化(因為沒有執行static靜态代碼塊,但是已經由類加載器進行了加載,且對靜态成員變量配置設定了存儲空間)
2. 對于靜态成員變量,使用final修飾與未使用final修飾(靜态常量與靜态非常量)之間的差別:
如果類中使用static和final修飾了,則該類在沒有初始化時,也可以直接通路其靜态常量。如Demo中的Mouse,并沒有執行Mouse類的靜态代碼塊,但依然可以通路靜态常量type,但是沒有final則不同,同樣沒有使用.class方式進行類加載時,即沒有對類進行初始化時,我們直接通路Cat類的靜态成員變量(非final修飾),會先對該Cat類進行初始化,才可以通路其靜态成員變量type