java反射(1) 之class.forName(""), 類名.class, 物件.getClass()區別

EmineWang發表於2013-11-08

1、先說class.forName("")

先看API

public static Class<?> forName(String className)
throws ClassNotFoundException返回與帶有給定字串名的類或介面相關聯的 Class 物件。呼叫此方法等效於: 


Class.forName(className, true, currentLoader)(此來源Class的另一個方法

public static Class<?> forName(String name,
                               boolean initialize,
                               ClassLoader loader)
                        throws ClassNotFoundException

其中 currentLoader 表示當前類的定義類載入器。
例如,以下程式碼片段返回命名為 java.lang.Thread 的類的執行時 Class 描述符。

Class t = Class.forName("java.lang.Thread")
呼叫 forName("X") 將導致命名為 X 的類被初始化。


true表示用載入器載入這個類生成Class物件的同時,並且初始化這個類。

package com.testclass;

public class TestClass {
	public static void main(String[] args) {
		try {
			Class c = Class.forName("com.testclass.Test");
			System.out.println(c.getName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

class Test {
	static {
		System.out.println("執行靜態塊,初始化類");
	}

	public Test() {
		System.out.println("構造方法執行");
	}
}

輸出:

執行靜態塊,初始化類
com.testclass.Test

說明當使用Class.forName("")進行反射生成Class物件的時候,執行了這個類的靜態程式碼,初始化了這個類


補充:Class.forName(xxx.xx.xx) 返回的是一個類, .newInstance() 後才建立一個物件 Class.forName(xxx.xx.xx);的作用是要求JVM查詢並載入指定的類,也就是說JVM會執行該類的靜態程式碼段 (來源http://blog.csdn.net/ozwarld/article/details/8277361)

2、類名.class

JVM將使用類A的類裝載器,將類A裝入記憶體(前提是:類A還沒有裝入記憶體),不對類A做類的初始化工作.返回類A的Class的物件

package com.testclass;

public class TestClass {
	public static void main(String[] args) {
		Class c = Test.class;
		System.out.println(c.getName());
	}
}

class Test {
	static {
		System.out.println("執行靜態塊,初始化類");
	}

	public Test() {
               System.out.println("構造方法執行"); 
        }
}
輸出:

com.testclass.Test

也就是說利用類名.class進行反射生成Class物件的時候,不會初始化這個類,更不會執行這個類的靜態程式碼



3、物件.getClass()

Class cl=物件引用.getClass();返回引用o執行時真正所指的物件所屬的類的Class物件(因為:兒子物件的引用可能會賦給父物件的引用變數中,也就是上轉型物件)

就是現有物件然後再通過這個物件用Class cl=物件引用.getClass()得到Class物件

但是在靜態方法中不能用this.getClass()得到這個類的Class物件。原因當然是靜態方法中不能用this的原因了










相關文章