https://blog.csdn.net/itachiwwwg/article/details/9003261
當java的源代碼中出現了和系統的lib庫中的包名與類名完全一樣的類時,系統應當怎么加載?
我們都知道在JVM啟動的時候會先調用bootstrap classloader 加載核心類,然后調用extClassLoader 加載系統擴展類,然后再調用APPClassLoader加載系統類,現在問題來了當我們在工程里創建一個從包名到類名都與系統已有的類完全一樣的類時會發生什么事情?請看下邊的實驗:
我以java.util.Date為例,在實驗中創建了一個與系統已有Date類一模一樣的Date類
- package java.util;
- public class Date {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODDO Auto-generated method stub
- Date d=new Date();
- d.hello();
- }
- private void hello(){
- }
- }
運行這段程序,系統會有如下結果
很明顯,程序在運行的時候選擇了系統中原有的java.util.Date類,並沒有選擇我們自己寫的Date類,這與先前提到的JVM的classloader的加載順序相一致,由於java.util屬於系統的核心類,在首次加載時即由bootstrape加載完畢,用戶的類Date應當由AppClassLoader進行加載,但是由於雙親委托機制的存在,AppClassLoader並不是立即進行加載,它需要先向其父加載器ExtClassLoader請求,由ExtClassLoader先加載,ExtClassLoader再向bootstrapeClassLoader請求加載,由於之前名為java.util.Date的類已經被bootstrape加載過了,所以后邊兩個加載器就不再對Date進行加載,因此看到的是系統報錯(因為系統中的Date類沒有main函數)
順帶提一下,對於Date類系統中有兩個包里都有它:java.util.Date以及java.sql.Date。當一個程序中僅僅出現Date時,系統會讓用戶選擇引入哪個包,如果人為的把兩個路徑都import了,系統只采納最先出現的import作為Date的對應類,因此若想在系統中兩個包里的Date都使用,需要在一個Date前寫全其完全類名即:java.util.Date d=new java.util.Date();