类加载及对象创建

来源:互联网 发布:linux dhcp安装 编辑:程序博客网 时间:2024/06/05 14:22

    首先说说可以引起类初始化的4种方法(jdk1.7中还有一种就不提了)

   1. new ,invokestatic, getstatic,putstatic

   2. 反射

   3. 主类包含main方法的类

   4. 父类先初始化,子类后初始化


    new方法会使用new关键字因此会引起类初始化,在初始化过程会调用类构造方法,初始化完成之后接着调用实例构造方法,因此

new方法会将这两者都进行调用从而生成实例对象,一般静态方法的调用只会引起初始化类构造方法的调用。在new方法执行过程中

会进行类的加载过程,生成Class对象(是由类加载器的方法loadClass->defineClass)。

    Class.forName(className)方法等效于Class.forName(className, true, currentLoader),这个方法会直接调用当前类的类加载器

进行类加载(可以自己制定类加载器进行加载loadClass->defineClass)生成了类Class对象并进行初始化过程,即调用类构造函数。详

情请看

    

    类名.class 这种方法虽然可以获取Class对象但是并没有进行类的初始化过程。

    实例.getClass方法,既然都有实例,之前肯定已经进行了初始化过程,即调用了类构造器和实例构造器,只不过返回已经生成的

Class对象。

    类加载器.loadClass方法加载类,并没有进行初始化,只是生成Class对象并没有进行初始化过程。

package dahua;public class Sample {static{System.out.println("s");}}

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;public class MyClassLoader extends ClassLoader {    private String name; // 类加载器的名字    private String path = "d:\\"; // 加载类的路径    private final String fileType = ".class"; // class文件的扩展名        public MyClassLoader(String name) {    super(); // 让系统类加载器成为该类加载器的父加载器        this.name = name;    }        public MyClassLoader(ClassLoader parent, String name) {        super(parent); // 显式指定该类加载器的父加载器        this.name = name;    }        @Override    public String toString() {        return this.name;    }        public String getPath() {        return path;    }        public void setPath(String path) {        this.path = path;    }    /**     * @param 类文件的名字     * @return 类文件中类的class对象     *      * 在这里我们并不需要去显示的调用这里的findclass方法,在上篇文章中,我们通过查看     * loadclass的源码可以发现,她是在loadclass中被调用的,所以这里我们只需重写这个方法,     * 让它根据我们的想法去查找类文件就ok,他会自动被调用     *      *      * defineClass()将一个 byte 数组转换为 Class 类的实例。必须分析 Class,然后才能使用它     * 参数:         * name - 所需要的类的二进制名称,如果不知道此名称,则该参数为 null         * b - 组成类数据的字节。off 与 off+len-1 之间的字节应该具有《Java Virtual Machine Specification            》定义的有效类文件的格式。         * off - 类数据的 b 中的起始偏移量         * len - 类数据的长度      */    @Override    public Class<?> findClass(String name) throws ClassNotFoundException {        byte[] data = this.loadClassData(name);//获得类文件的字节数组        return this.defineClass(name, data, 0, data.length);//    }    /**     *      * @param 类文件的名字     * @return 类文件的 字节数组     * 通过类文件的名字获得类文件的字节数组,其实主要就是用     * 输入输出流实现。     */    private byte[] loadClassData(String name) {        InputStream is = null;        byte[] data = null;        ByteArrayOutputStream baos = null;        try {            this.name = this.name.replace(".", "\\");            is = new FileInputStream(new File(path + name + fileType));            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;  }    public static void main(String[] args) throws Exception {        //创建一个loader1类加载器,设置他的加载路径为d:\\serverlib\\,设置默认父加载器为系统类加载器        MyClassLoader loader1 = new MyClassLoader("loader1");        Class str = loader1.loadClass("dahua.Sample");        System.out.println("finish "+str.toString());    }}


0 1
原创粉丝点击