类的隐式(自动)加载和显式(非自动)加载

所属文集:ClassLoader串烧


关键字 Import , forName , loadClass 藕断丝连

问题

通常我们都知道我们写的类,会被JVM加载,那都怎么被加载呢?

答案

  1. 如果我们的类是import的方式(导入包,导入类)引入的,那么JVM自动帮我们去加载;
  2. 另外一种情况是我们指定类加载器去加载;如使用Class.forName(类名 ,指定的classLoader)或者 指定的classLoader.loadClass(xxx)
1.自动加载(import):
  1. 验证我们的代码中所使用(import导入)的类,在使用的时候会被当前类加载器自动加载,就是使用当前类加载器loadClass方法。
  2. 当前类加载器怎么理解, 当前类被哪个类加载器加载的,那么这个类加载器就叫做这个类的当前类加载器。那么这个类中通过import方式引入了其他类,就被JVM自动的调用当前类加载器的loadClass方法加载。

这个很好验证,ClassLoader的loadClass方法里自己打个断点,调试一下。


2.非自动加载:

非自动加载就是我们指定一个累加器去加载类,根据需要forName , loadClass二选一,问自己一个问题,forName是不是要遵守双亲委派模型?双亲委派的代码逻辑在ClassLoader#loadClass中,那是不是forName还会调用ClassLoader的loadClass的方法逻辑呢?会的

验证一下 接口:

public interface MsgCenter {
    public boolean sendMsg(String msg);
}

实现

--
public class MsgValidater {

    public boolean validate(String msg){
        return  true;
    }
}
public class MsgCenterImpl implements MsgCenter {
    @Override
    public boolean sendMsg(String msg) {
        // import MsgValidater类型
        return new MsgValidater().validate(msg);
    }
}

测试:
1.appClassLoader 加载接口
2.子加载器,forName方式加载实现类

  1. 实现类实例化,并赋值给接口类.调用sendMsg方法,此方法内引用了MsgValidater类.
/**
     * 把MsgCenterImpl.class 移动到子加载器的加载路径中.保证只有子加载器可加载.
     */
    @Test
    public void testImportLoadClass(){
        CustomClassLoader01 customClassLoader01 = new CustomClassLoader01(ClassLoader.getSystemClassLoader());
        try {
            //appClassloader 加载 接口
            MsgCenter msgCenter = null;
            //子加载器,加载 实现类
            Class aClass = Class.forName("com.rock.MsgCenterImpl",false,customClassLoader01);
            //赋值 接口 = 实现类 ;这是可以的,因为子加载器可见父加载器所加载的类.
            msgCenter =(MsgCenter)aClass.newInstance();
            boolean hello = msgCenter.sendMsg("hello");
            System.out.println("after sendMsg");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

输入结果

CustomClassLoader start  load class :com.rock.MsgCenterImpl  ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader getParent().loadClass(name) : ClassNotFoundException
CustomClassLoader loadClassData : com.rock.MsgCenterImpl
//以上信息说明:forName方法通过自定义类加载器的loadClass方法加载了com.rock.MsgCenterImpl

CustomClassLoader start  load class :com.rock.MsgCenter  ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader start  load class :java.lang.Object  ; resolve : false
CustomClassLoader findLoadedClass : null
//以上信息说明:子加载器 委托父加载器加载 com.rock.MsgCenter ,java.lang.Object

CustomClassLoader start  load class :com.rock.classLoader.MsgValidater  ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader getParent().loadClass(name) : ClassNotFoundException
CustomClassLoader loadClassData : com.rock.classLoader.MsgValidater
//以上信息说明:自加载器加载了com.rock.classLoader.MsgValidater

after sendMsg
//以上信息说明,实现类赋值给接口后,调用接口的方法执行成功.
类的隐式(自动)加载和显式(非自动)加载_第1张图片
image.png
命名空间
image.png

参考传送门:Class.forName和ClassLoader.loadClass

你可能感兴趣的:(类的隐式(自动)加载和显式(非自动)加载)