class.forName与classLoader区别

题记:

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

区别:

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

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

加载:通过累的全限定名获取二进制字节流,将二进制字节流转换成方法区中的运行时数据结构,在内存中生成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初始化的时候运行静态代码块相关

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

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

回复  8888可以领取面试资料

ref:

https://www.cnblogs.com/jimoer/p/9185662.html

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术王老五

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值