?(1)阿里的面試官問我,可以不可以自己寫個String類
答案:不可以,因為 根據(jù)類加載的雙親委派機制,會去加載父類,父類發(fā)現(xiàn)沖突了String就不再加載了;
(2)能否在加載類的時候,對類的字節(jié)碼進(jìn)行修改
答案:可以,使用Java探針技術(shù),可以參考:Java探針-Java Agent技術(shù)-阿里面試題
1.什么是類加載器?
? 類加載器就是Java運行時環(huán)境(Java Runtime Environment)的一部分,負(fù)責(zé)動態(tài)加載Java類到Java虛擬機的內(nèi)存空間中。恩看了這個介紹就知道了~~~原來平常的.class文件是通過這個加載器,加載到內(nèi)存中的。
2.類加載器的種類以及作用
1)Bootstrap ClassLoader
負(fù)責(zé)加載$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++實現(xiàn),不是ClassLoader子類
2)Extension ClassLoader
負(fù)責(zé)加載java平臺中擴展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的jar包
3)App ClassLoader(SystemClassLoader)
負(fù)責(zé)記載classpath中指定的jar包及目錄中class
4)Custom ClassLoader
屬于應(yīng)用程序根據(jù)自身需要自定義的ClassLoader,如tomcat、jboss都會根據(jù)j2ee規(guī)范自行實現(xiàn)ClassLoader
OK那么好了,我們現(xiàn)在知道了什么是類加載器以及它的種類及作用了,那么現(xiàn)在問題來了,為什么我們自己寫的Sring類能否被加載到呢?我們自己寫一個來看看
首先,寫了一個跟JAVA自帶的String類一個一樣的String,包名也一樣就是在構(gòu)造方法里面多了一行輸出。
publicString(){
this.value =newchar[0];
System.out.println("==================");
? ? }
也就是說只要調(diào)用了我們自己寫的String類得話應(yīng)該是有輸出的,接下來我們來試試:
importjava.lang.String;
publicclassTest{
publicstaticvoidmain(String[] args){
String test =newString();
test ="測試";
?? ?System.out.println(test);
}
}
運行結(jié)果如下:

可以看到調(diào)用的是系統(tǒng)的String類,沒有輸出。
這是為什么呢?查閱了一些資料終于發(fā)現(xiàn)問題所在,這就是類加載器的委托機制。
3.類加載器的委托機制
? 從JDK1.2開始,類的加載過程采用父親委托機制。這種機制能更好的保證java平臺的安全。在此委托機制中,除了Java虛擬機自帶的根類加載器以外,其余的類加載器都有且只有一個父加載器。當(dāng)Java程序請求加載器loader1加載Sample類時,loader1首先委托自己的父加載器去加載Sample類,若父加載器能加載,則由父加載器完成加載任務(wù),否則才由加載器loader1本身加載Sample類。
好吧~~~這下看明白了類加載器有個加載順序我們來看一下這個加載順序

加載過程中會先檢查類是否被已加載,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個classloader已加載就視為已加載此類,保證此類只所有ClassLoader加載一次。而加載的順序是自頂向下,也就是說當(dāng)發(fā)現(xiàn)這個類沒有的時候會先去讓自己的父類去加載,父類沒有再讓兒子去加載,那么在這個例子中我們自己寫的String應(yīng)該是被Bootstrap ClassLoader加載了,所以App ClassLoader就不會再去加載我們寫的String類了,導(dǎo)致我們寫的String類是沒有被加載的。