天天看點

比較兩種類加載方式-使用.class和Class.forName(String className)

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