理解class.forName()(good--字节码层面)
使用jdbc方式連接數據庫時會使用一句代碼Class.forName(String?className).這句話是什么意思呢?首先說一點Class.forName(String?className)這個方法的作用是裝載className這個字符串指定的類。
官方文檔
返回與帶有給定字符串名的類或接口相關聯的?Class?對象。調用此方法等效于:
??Class.forName(className,?true,?currentLoader)
?其中?currentLoader?表示此類的定義類加載器。
例如,以下代碼片段返回?java.lang.Thread?類的運行時?Class?描述符。
???Class?t?=?Class.forName("java.lang.Thread")
?調用?forName("X")?將導致名為?X?的類被初始化。
參數:
className?-?所需類的完全限定名。
返回:
具有指定名的類的?Class?對象。
通俗的說就是:獲得字符串參數中指定的類,并初始化該類
類裝載
類裝載就是把一個類或是一個接口的字節碼文件,通過解析該字節碼來構建代表這個類或是這個接口的實例的過程。?
這個字節碼文件來源可能是壓縮包、網絡、運行時編譯出的或者自動生成的class文件,jvm?spec沒有規定必須從什么地方加載。
類裝載的兩種方式:
1.Class?c1?=?Class.forName?("java.lang.String");?
2.ClassLoader?cl?=?new??ClassLoader();?
Class?cl.loadClass(?String?name,?boolean?resolve?);
?
兩種裝載方法的區別:
不同的類裝載器
??Class.forName是從指定的classloader中裝載類,如果沒有指定,也就是一個參數的時候,是從裝載當前對象實例所在的classloader中裝載類。
??而ClassLoader的實例調用loadclass方法,是指從當前ClassLoader實例中調用類,而這個實例與裝載當前所在類實例的Classloader也許不是同一個.?
??????說白了就是他們實現裝載的時候,使用的類裝載器的指定是不同的。那為什么使用不同的ClassLoader來裝載類呢?
??? ??其實使用多個classloader加載類的情況非常常見,比如說我們的app?server都是這樣的.?在Web與EJB間,?他們的classLoader就是不同的,這樣做的目的就是為了避免兩者間類裝載的相互干擾。
是否實例化類
??????Class的裝載分了三個階段,loading(裝載),linking(連接)和initializing(實例化)分別定義在The?Java?Language?Specification的12.2,12.3和12.4。
?Class.forName(className)實際上是調用Class.forName(className,?true,?this.getClass().getClassLoader())。注意第二個參數,是指Class被loading后是不是必須被初始化。
? ??ClassLoader.loadClass(className)實際上調用的是ClassLoader.loadClass(name,?false),第二個參數指出Class是否被link。
? ??區別就出來了。Class.forName(className)裝載的class已經被實例化,而ClassLoader.loadClass(className)裝載的class還沒有被link,所以就更談不上實例化了。
??一般情況下,這兩個方法效果一樣,都能裝載Class。但如果程序需要Class被實例化,就必須用Class.forName(name)了。
例如,在JDBC中加載mysql的驅動類時(關于注冊jdbc驅動請參看另外一篇文章,jdbc注冊驅動的三種方式),Class.forName("com.mysql.jdbc.Driver"),
如果換成getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行,因為它只是向jvm裝載了Driver并沒有實例化,就不能執行響應的操作。
?打開com.mysql.jdbc.Driver的源代碼看看,
// Register ourselves with the DriverManager static {try {java.sql.DriverManager.registerDriver(new Driver());} catch (SQLException E) {throw new RuntimeException("Can't register driver!");} }可以看到,Driver在static塊中會注冊自己到java.sql.DriverManager。而static塊就是在Class的初始化中被執行。所以這個地方就只能用Class.forName(className)。
?
資源
http://blog.csdn.net/yanwushu/article/details/75747131.http://www.iteye.com/topic/15039?
2.Class.forName和ClassLoader.loadClass的比較
http://blog.csdn.net/lu7kang/article/details/5576043?
3.自定義ClassLoader?
http://software.ccidnet.com/pub/disp/Article?columnID=294&articleID=25857&pageNO=1?
?4.ClassLoader分析?
http://blog.csdn.net/longdick/article/details/1873795?
轉載于:https://www.cnblogs.com/softidea/p/4000137.html
總結
以上是生活随笔為你收集整理的理解class.forName()(good--字节码层面)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Json入门及基本应用
- 下一篇: 将一列数据转换成一个字段数据,逗号分隔