在上一次【】已经阅读了ClassLoader类的官方doc,不过只阅读了一部分,这次继续往下去读:
上面这句话是非常之重要,需要好好读一读。
至此!一字不落的将ClassLoader的官方说明给看完了,里面涉及到一些不太清楚的方法,没关系,重在对它有一个基本的认识,接下来咱们来自定义一下类加载器来实践一下:
要自定义首先肯定得去继承ClassLoader这个抽象类:
然后定义一些变量,在创建类加载器时是需要传递的信息:
但是这个构造方法还得调用一下父类的,如下:
为什么呢?先看一下这个构造的官方说明:
而再看一下getSystemClassLoader()方法的说明:
也就是这句调用父类的构造的作用就是来指定咱们自定义的类加载器的双亲是系统类加载器。
另外还需要定义一个构造方法,如下:
那这个调用父类带参数的构造又有啥含义呢?
比较容易理解,也就是这种构造就是咱们自己可以定义自己的双亲了。
接下来则根据咱们在阅读ClassLoader中自定义类的方式来继续,如下:
具体如何来加载呢?其实就是j2se读字节流了,不难理解,直接贴上代码:
好,接着再来覆写父类的另一个重要方法,也是来自于ClassLoader的javadoc说明,如下:
依葫芦画瓢:
接下来来使用一下咱们自定义的类加载器加载一下类,如下:
public class MyTest16 extends ClassLoader { private String classLoaderName; private final String fileExtension = ".class";//要加载的字节码文件的扩展名 public MyTest16(String classLoaderName) { super();//将系统类加载器当作该类加载器的父加载器 this.classLoaderName = classLoaderName; } public MyTest16(ClassLoader parent, String classLoaderName) { super(parent);//显示指定该类加载器的父加载器 this.classLoaderName = classLoaderName; } @Override public String toString() { return "[" + classLoaderName + "]"; } @Override protected Class findClass(String className) throws ClassNotFoundException { byte[] data = this.loadClassData(className); return this.defineClass(className, data, 0, data.length); } private byte[] loadClassData(String name) { InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null; try { this.classLoaderName = this.classLoaderName.replace(".", "/"); is = new FileInputStream(new File(name + this.fileExtension)); baos = new ByteArrayOutputStream(); int ch = 0; while (-1 != (ch = is.read())) { baos.write(ch); } data = baos.toByteArray(); } catch (Exception ex) { ex.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (Exception ex) { ex.printStackTrace(); } } return data; } private static void test(ClassLoader classLoader) throws Exception { Class clazz = classLoader.loadClass("com.jvm.classloader.MyTest1"); Object object = clazz.newInstance(); System.out.println(object); } public static void main(String[] args) throws Exception { MyTest16 myTest16 = new MyTest16("loader1"); test(myTest16); }}
编译运行:
是不是很兴奋!!不过对于这个实现目前还有很多疑问,用到了findClass()、loadClassData()系统方法,具体是啥含义这里先不用纠结,在之后的学习会不断深入的,目前先对自定义类加载器有一个大体的认识,能正常的将程序跑起来达到预期既可。