class.forName与classLoader区别

题记:

记录一下java反射中的一些面试问题html

区别:

@CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

第二个参数是true,表示是否初始化,默认是初始化,一旦初始化,就会出发对象的静态代码块和静态参数的初始化,请看类的装在过程java

加载:经过累的全限定名获取二进制字节流,将二进制字节流转换成方法区中的运行时数据结构,在内存中生成Java.lang.class对象; 

连接:执行下面的校验、准备和解析步骤,其中解析步骤是能够选择的; 

  校验:检查导入类或接口的二进制数据的正确性;(文件格式验证,元数据验证,字节码验证,符号引用验证) 

  准备:给类的静态变量分配并初始化存储空间; 

  解析:将常量池中的符号引用转成直接引用; 

初始化:激活类的静态变量的初始化Java代码和静态Java代码块,并初始化程序员设置的变量值。

 代码示例:

@Data
@Builder
public class Product implements Serializable {

    private static String staticMethod = staticMethod();

    static {
        System.out.println("静态代码块执行");
    }

    private String name;

    private String address;

    private static String staticMethod(){

        System.out.println("静态方法执行");
        return "静态方法块执行";
    }

}

执行实例:

public class Demo2 {

    @Test
    public void test1() throws ClassNotFoundException {
        System.out.println("class.forName 执行================");
        Class.forName("com.edward.sg.owner.server.Product");
        System.out.println("classLoader 执行=================");
        ClassLoader.getSystemClassLoader().loadClass("com.edward.sg.owner.server.Product");
    }

}

执行结果 

class.forName 执行================
静态方法执行
静态代码块执行
classLoader 执行=================

classLoader执行结果能够看出没有进行类的初始化,只是将类加载到虚拟机中,class.forName进行类的初始化程序员

jdbc中使用了class.forname进行类的初始化,加载静态方法面试

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

DriverManager.registerDriver(new Driver())和 Class.forName(),其中DriverManager.registerDriver会致使实例化了两次Driver与Driver初始化的时候运行静态代码块相关sql

Spring IoC 的 Lazy loading 有关, Spring IoC 为了加快初始化速度, 所以大量使用了延时加载技术. 而使用 classloader 不须要执行类中的初始化代码, 能够加快加载速度, 把类的初始化工做留到实际使用到这个类的时候(感兴趣的同窗还能够看看 IOC中的循环依赖的问题 https://www.jianshu.com/p/f0c005c7354b数据结构

欢迎关注做者公众号交流以及投稿ui

ref:code

http://www.javashuo.com/article/p-pwygcsas-be.htmlserver

https://www.cnblogs.com/zabulon/p/5826610.htmlhtm

相关文章
相关标签/搜索