Java面試Offer直通車
文章目錄
Pre
自定義類加載器
我們瞭解了雙親委派機制後,那自定義類加載器相對就很容易了 , 只需要繼承 java.lang.ClassLoader 類 ,重寫findClass方法即可
該類有兩個核心方法:
-
一個是loadClass(String, boolean),實現了雙親委派機制 .
-
一個方法是findClass,默認實現是空方法
所以自定義類加載器主要是重寫findClass方法
演示
Step1 : 複製一個Boss1 的類,編譯後,取到Boss1.class 備用
Step2 : 刪除Boss1類
Step3 : 編寫自定義ClassLoader
抽象類CLassLoader ,我們自定義的ClassLoader只需要繼承抽象類ClassLoader,重寫loadClass方法
package com.gof.facadePattern;
import java.io.FileInputStream;
import java.lang.reflect.Method;
/**
* @author 小工匠
* @version v1.0
* @create 2020-06-11 23:09
* @motto show me the code ,change the word
* @blog https://artisan.blog.csdn.net/
* @description
**/
public class MyClassLoaderTest {
static class MyClassLoader extends ClassLoader {
private String classPath;
public MyClassLoader(String classPath) {
this.classPath = classPath;
}
private byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name
+ ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
//defineClass將一個字節數組轉爲Class對象,這個字節數組是class文件讀取後最終的字節數組。
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
}
public static void main(String args[]) throws Exception {
//初始化自定義類加載器,會先初始化父類ClassLoader,其中會把自定義類加載器的父加載器設置爲應用程序類加載器AppClassLoader
MyClassLoader classLoader = new MyClassLoader("D:/artisan");
//D盤創建 artisan/com/gof/facadePattern 目錄,將Boss類的複製類Boss1.class丟入該目錄
Class clazz = classLoader.loadClass("com.gof.facadePattern.Boss1");
Object obj = clazz.newInstance();
// 調用sout方法
Method method = clazz.getDeclaredMethod("sout", null);
method.invoke(obj, null);
System.out.println(clazz.getClassLoader().getClass().getName());
}
}
defineClass 複用ClassLoader的即可 ,主要功能是將一個字節數組轉爲Class對象
自定義類加載器的父加載器是AppClassLoader , 但並不是說自定義ClassLoader的父類是AppClassLoader,這一點一定不要搞錯了。
Step 4: 自定義目錄存放Boss1.class
Step 5 : 運行結果
注意事項
Boss1 生成class後,需要把Boss1 刪掉,不然雙親委派(我們並沒有重寫loadClass方法),它又從AppClassLoader加載了 。 需要確保你自定義加載的Boss1 在其父加載器中都不存在。