日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Class.forName解析以及使用

發布時間:2025/7/14 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Class.forName解析以及使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

這個類在剛學習Java連接數據庫的時候見到這個這種寫法,并且工作這么多年,也許是接觸的東西比較少,這種用法也就只有在自己手寫數據庫連接代碼的時候見過,在其他的時候還真是沒見過。

在Class類中,對此方法有如下聲明

方法重載了三次。

查看第一個forName方法的聲明為:

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

首先在這個方法中,使用到了Reflection.getCallerClass(),返回是調用者對象

針對getCallerClass這個方法,這個方法是native的,聲明如下:

@CallerSensitive public static native Class getCallerClass();

由于是native方法,就暫時不跟進去了,這個方法的意思返回調用者 class對象),也就是說是誰調用調用了我這個類的方法。如下示例:

public class ReflectionCaller {public static void main(String[] args) {InnerClass i = new InnerClass();i.innerMethod();} }class InnerClass {public void innerMethod() {System.out.println(Reflection.getCallerClass());} }

運行以上代碼,輸出的結果是:

也就是ReflectionCaller這個類對象。這個方法還是比較有趣的,如果在以后我們自己寫代碼的時候,想知道誰在調用我這些的這些方法,就可以跟蹤出來了。

獲取調用者信息以后,會調用Class.forname0方法,進行加載和初始化類。看到forname0這個方法又是一個native方法。

private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller)throws ClassNotFoundException;

這個方法的作用是根據name加載傳遞過來的類,并且根據initialize來決定是否要進行初始化,所謂初始化指的是加載里面的靜態塊之類的。加載的時候采用caller相同的類加載器記性加載。

?

從中可以看出Class.forName和Classloader.lodeclass的區別是什么,Class.forName可以加載類并且控制是否要對類進行初始化,而ClassLoader.loadClass只對類進行加載,不進行初始化。

?

知道了Class.forName 的作用,那接下來就看一下針對連接mysql的具體問題。

根據第一節,可以看到連接字符串為:

Class.forName("com.mysql.jdbc.Driver");

也就是說會加載com.mysql.jdbc.Driver這個類,并且進行初始化。找到mysql-connector-java.jar的源碼,這個類非常簡單。

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()} }

這個類中 就一個靜態塊和一個無參的構造函數,通過靜態塊的內容可以看出,實例了的一個Driver,然后注冊到DriverManagerDriverManager把這個Driver存儲到了一個CopyOnWriteArrayList中。

同時Driver還繼承了AbandonedConnectionCleanupThread這個類,這個類繼承Thread,啟動一個守護線程,然后清理廢棄的類對象。

以上就是我們在連接mysql時,Class.forName的功能。但是需要注意的是
Java 的SQL框架允許多個數據庫的Driver,每一個Driver都要實現java.sql.Driver接口,針對給出來的連接數據庫的請求,DriverManager嘗試去load盡可能多的它找到的drivers,然后根據這些driver嘗試使用給出來的數據庫連接字符串去嘗試連接數據庫。
在mysql的NonRegisteringDriver中強烈建議,每個驅動程序類應該盡可能的小和獨立,這樣在加載和查詢驅動類的時候,才不會引入大量的支持代碼。

?

轉載于:https://my.oschina.net/u/2457218/blog/818082

總結

以上是生活随笔為你收集整理的Class.forName解析以及使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。