题记:
记录一下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