引出問題
今天在做一個簡單的測試,自定義String類,代碼如下:
package java.lang;
/**
* Created By zby on 23:03 2019/11/12
* 自定義<code>String</code>類
*/
public class String {
public static void main(String[] args) {
new String();
}
}
結果報錯了:
你仔細看報錯的信息,你會感覺很疑惑,我明明在我自定義的String中寫了main方法,爲什麼還是會報錯呢?這就涉及到了雙親委派模式。
雙親委派
類加載器
再說雙親委派時,我們就得不說類加載器。類加載器並不神祕,只是我們覺着神祕了。
當JVM將Java源代碼轉化爲字節碼時,類加載器就加載和初始化字節碼文件。至於它能不能運行,以及運行效果,類加載器就不關注了,這由execution engine來做的。
類加載器普遍分爲以下幾種類型:
啓動類加載器(Bootstrap Class Loader)這是由c++來寫的,加載的是Javahome/jre/lib/rt.jar,因而,我們有時候通過類似如下的代碼,拿不到object的bootstrap類加載器的對象,因爲Java是拿不到c++的對象,object類存在於rt.jar包中的。
System.out.println(Object.class.getClassLoader());
擴展類加載器(Extension Class Loader),這是由Java來寫的,加載的是Javahome/jre/lib/ext/*.jar.
應用類加載器(APPClassLoder),這是加載classPath下面的類。
我麼通過以下代碼來看這幾個類加載器:
public class ClassLoaderCheck {
public static void main(String[] args) {
System.out.println(ClassLoaderCheck.class.getClassLoader().getParent().getParent());
System.out.println(ClassLoaderCheck.class.getClassLoader().getParent());
System.out.println(ClassLoaderCheck.class.getClassLoader());
System.out.println("=================");
System.out.println(Object.class.getClassLoader());
}
}
雙親委派
我們自定義的類通過類加載器實例化對象時,類加載器會向上查找父類加載器所在的類對象。如果我們自定義中的類與父類加載器所加載的類對象一致,如果當前類對象沒有我們定義的某個方法,其會報錯,正如上面的string報的錯。
如果任何一個父類加載器都加載不了我們自定義的類,那麼,纔是用appClassLoder類加載器,加載我們自定義的類。
這就是雙親委派模式,即委派給父類加載器。這樣就不允許用戶串改jdk的源碼,也保證了代碼的安全。