題記:
記錄一下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