首頁 > 遊戲
面試官:Class.forName 和 ClassLoader.loadClass 有什麼區別?
由 當代程式設計師 發表于 遊戲2023-01-06
簡介getCallerClass() 方法獲取類載入器來載入類public static Class forName(String name, boolean initialize,ClassLoader loader)throws Class
asi loader是什麼
Class。forName 和 ClassLoader。loadClass 都可以用來反射載入一個類,主要有2種區別:
1 使用的類載入器不一樣
Class。forName 最終是使用呼叫方的 ClassLoader 來載入類,在程式碼中使用 Reflection。getCallerClass() 方法獲取類載入器來載入類
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
SecurityManager sm = System。getSecurityManager();
if (sm != null) {
caller = Reflection。getCallerClass();
if (sun。misc。VM。isSystemDomainLoader(loader)) {
// 使用呼叫方的 ClassLoad 載入類
ClassLoader ccl = ClassLoader。getClassLoader(caller);
if (!sun。misc。VM。isSystemDomainLoader(ccl)) {
sm。checkPermission(
SecurityConstants。GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
ClassLoader。loadClass 遵循類載入的雙親委派模型類載入類,在程式碼中使用 ClassLoader parent 載入類
// The parent class loader for delegation
if (parent != null) {
c = parent。loadClass(name, false);
}
雙親委託模型:當一個類載入器接收到一個類載入的任務時,不會立即展開載入,而是將載入任務委託給它的父類載入器去執行,每一層的類都採用相同的方式,直至委託給最頂層的啟動類載入器為止。如果父類載入器無法載入委託給它的類,便將類的載入任務退回給下一級類載入器去執行載入。
2 類的裝載過程不一樣
類的裝載過程為:
連結
|
————————————————
載入 ——> | 驗證 ——> 準備 ——> 解析| ——> 初始化 ——> 使用 ——> 解除安裝
————————————————
Class。forName 會裝載類到初始化階段,因此會執行類中的靜態方法塊,呼叫 forName0 時傳入的 initialize 為 true
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection。getCallerClass();
// initialize = true
return forName0(className, true, ClassLoader。getClassLoader(caller), caller);
}
ClassLoader。loadClass 會裝載類到載入節點,不會執行連結操作,因此不會執行類中的靜態方法塊,在程式碼中呼叫 loadClass 時傳入的 resolve 為 false,表示不連結類
if (parent != null) {
// resolve = false
c = parent。loadClass(name, false);
}
如:
class Test {
static {
System。out。print(“loaded”);
}
}
使用 Class。forName 載入 Test 類會輸出 “loaded”,而使用 ClassLoader。loadClass 載入則不會輸出 “loaded”