当java的源代码中出现了和系统的lib库中的包名与类名完全一样的类时,系统应当怎么加载?

    我们都知道在JVM启动的时候会先调用bootstrap classloader 加载核心类,然后调用extClassLoader 加载系统扩展类,然后再调用APPClassLoader加载系统类,现在问题来了当我们在工程里创建一个从包名到类名都与系统已有的类完全一样的类时会发生什么事情?请看下边的实验:

    Java类与lib同包同名 - 图1

    我以java.util.Date为例,在实验中创建了一个与系统已有Date类一模一样的Date类

    1. package java.util;
    2. public class Date {
    3. /**
    4. * @param args
    5. */
    6. public static void main(String[] args) {
    7. // TODDO Auto-generated method stub
    8. Date d=new Date();
    9. d.hello();
    10. }
    11. private void hello(){
    12. }
    13. }

    运行这段程序,系统会有如下结果

    Java类与lib同包同名 - 图2

    很明显,程序在运行的时候选择了系统中原有的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();