如果想在Java运行过程中动态载入外部类,就要用到Java的类装载器。其实这也是Java虚拟机运行的机理之一,在虚拟机刚刚启动时,会载入一系列的类装载器,这些类装载器之间存在树形的父子关系,通常,根类装载器负责最初的核心类的装载(包括一些Java核心包的类),之后还会有System类装载器、上下文类装载器等等(具体的不是很清楚了),反正记住一点,当一个类装载器想要加载某个类时(比如你想new一个某某类),首先会问他的父装载器有没有这个类,如此上溯到树根,如果都没有再自己去找,也就是所谓的“委托”机制。但是这样会引出一个谁来装载第一个类加载器的问题,这个其实是靠一个BootStrap的类装载器完成的,它是一个用本地代码编写的类装载器,之后再逐步把其他类装载器加载进来,整个jvm就跑起来了
    罗嗦了这么多,其实是想说明一下怎样实现一个自己的类加载器。就我个人所知,通常是从URLClassLoader派生。这个URLClassLoader我们可以查查手册,是用于从特定URL地址加载类的(比如你要的jar远在因特网的另一端),但是URL同样可以表示本地路径,所以网上大部分示例都是派生URLClassLoader,然后调用它的addURL,也就是把你的class文件或者jar文件所在的路径添加到你的类加载器中
    URLClassLoader还提供了findClass方法,顾名思义就是查找某个类并返回该类的Class对象,然后你就可以利用反射来动态创建类了。
    但是,不要被findClass的名字给骗了,这个方法不仅仅是“查找”某个类,而且还包括自动加载类(如果找到了的话),可以查Java手册详细了解。所以如果你两次findClass相同的类,那么会抛出duplicate class definition (重复的类定义)异常,解决的方法是自己覆盖该方法,代码如下:
public Class findClass(String name) throws ClassNotFoundException{
  Class c = this.findLoadedClass(name);
  if(c == null)
   return super.findClass(name);
  else
   return c;
 }
ClassLoader本身有个findLoadedClass,这个方法只会在已载入的类里面查找,找不到就返回null,这样就可以避免两次加载同样的类了 
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐