Java的jdbc中 DriverManager.registerDriver(driver); //注冊驅動 有沒有必要寫的思考


加載數據庫驅動的時候,有如下部分代碼:

1          //1) 注冊驅動程序
2          //給java.sql.Driver接口的引用賦值 com.mysql.jdbc.Driver 實現類對象
3          Driver driver = new com.mysql.jdbc.Driver();
4          DriverManager.registerDriver(driver);   //注冊驅動

先到數據庫驅動包看下這個Driver類:

 

可以看到這個類里面有個static語句塊,這里先來復習以下,什么時候會加載static語句塊,有如下情況:

 當一個類被主動使用時,Java虛擬就會對其初始化,類初始化的時候,就會執行靜態代碼。如下六種情況為主動使用:

  1. 當創建某個類的新實例時(如通過new或者反射,克隆,反序列化等)

  2. 當調用某個類的靜態方法時

  3. 當使用某個類或接口的靜態字段時

  4. 當調用Java API中的某些反射方法時,比如類Class中的方法,或者java.lang.reflect中的類的方法時

  5. 當初始化某個子類時

  6. 當虛擬機啟動某個被標明為啟動類的類(即包含main方法的那個類)

Java編譯器會收集所有的類變量初始化語句和類型的靜態初始化器,將這些放到一個特殊的方法中:clinit。

 特別要注意的是:使用final修飾的靜態字段,在調用的時候不會對類進行初始化!以及類被加載了不一定就會執行靜態代碼塊,只有一個類被主動使用的時候,靜態代碼才會被執行

 

那么回到原來的問題,在創建Driver這個對象的時候:

Driver driver = new com.mysql.jdbc.Driver();

必然會執行其內的static語句塊的,其static語句塊的作用就和:

DriverManager.registerDriver(driver); 

這段代碼的作用是一樣的,所以有必要再寫一次這行代碼嗎?

我試着刪除了這行代碼,發現還是能順利連接到數據庫。

查找了一些資料,找到了計算driver數量的方法,如下所示:

 1 public class jbdctest01 {
 2     public static void main(String[] args) throws ClassNotFoundException, SQLException {
 3         //1) 注冊驅動程序
 4         //給java.sql.Driver接口的引用賦值 com.mysql.jdbc.Driver 實現類對象
 5 //          Driver driver = new com.mysql.jdbc.Driver();
 6 //          DriverManager.registerDriver(driver);   //注冊驅動
 7         //注冊驅動也可以使用Class.forName()創建Class對象時,會執行類的靜態代碼塊, 在com.mysql.jdbc.Driver類的靜態代碼塊中,注冊驅動
 8         Class.forName("com.mysql.jdbc.Driver");
 9         //2)在當前程序與 數據庫服務器建立連接
10 //        Connection connection = DriverManager.getConnection("jdbc:mysql://數據庫服務器IP地址:MySQL服務的端口號/數據庫名", "登錄服務器的用戶名", "登錄密碼");
11         Enumeration<Driver> drivers = DriverManager.getDrivers();
12 
13         int nums = 0;
14         //使用while循環來遍歷驅動的個數
15         while(drivers.hasMoreElements()) {
16             nums ++;
17             //打印出驅動
18             System.out.println(drivers.nextElement());
19         }
20         //打印出驅動個數
21         System.out.println("驅動個數:" + nums);
22   }
23 }

測試結果如圖所示:

 

用反射的方法加載驅動,驅動數為一個,這是意料之中的事情,在創建Driver這個對象時,會執行static中的代碼塊,因此會加載驅動,且數量為1

接下來測試,另外一種方法,代碼如下:

 1 public class jbdctest01 {
 2     public static void main(String[] args) throws ClassNotFoundException, SQLException {
 3         //1) 注冊驅動程序
 4         //給java.sql.Driver接口的引用賦值 com.mysql.jdbc.Driver 實現類對象
 5             Driver driver = new com.mysql.jdbc.Driver();
 6             DriverManager.registerDriver(driver);   //注冊驅動
 7         //注冊驅動也可以使用Class.forName()創建Class對象時,會執行類的靜態代碼塊, 在com.mysql.jdbc.Driver類的靜態代碼塊中,注冊驅動
 8        //Class.forName("com.mysql.jdbc.Driver");
 9         //2)在當前程序與 數據庫服務器建立連接
10 //        Connection connection = DriverManager.getConnection("jdbc:mysql://數據庫服務器IP地址:MySQL服務的端口號/數據庫名", "登錄服務器的用戶名", "登錄密碼");
11         Enumeration<Driver> drivers = DriverManager.getDrivers();
12 
13         int nums = 0;
14         //使用while循環來遍歷驅動的個數
15         while(drivers.hasMoreElements()) {
16             nums ++;
17             //打印出驅動
18             System.out.println(drivers.nextElement());
19         }
20         //打印出驅動個數
21         System.out.println("驅動個數:" + nums);
22   }
23 }

測試結果如圖所示:

 

 

 

 

可以看到結果是2

接下來注釋掉:DriverManager.registerDriver(driver); 這行代碼,可以看到輸出結果:

 

可以看到驅動個數為1個,說明了DriverManager.registerDriver(driver);這行代碼可以去掉,如果加上,就會出現了兩個驅動,因為在創建Driver這個對象的時候,其內的static語句塊會自動執行了。

 

另外還有一個小的疑問,就是一個對象執行的時候,是先創建類還是先執行其內的靜態方法呢?我特意寫了一個程序試了一下:

 1 public class Teststatic {
 2     public  Teststatic(){
 3         System.out.println("看看誰先被執行");
 4 
 5     }
 6     static {
 7         System.out.println("我被執行了,哈哈哈");
 8     }
 9 }
10  class  T {
11     public static void main(String[] args) {
12         Teststatic a = new Teststatic();
13 
14     }
15 }

運行結果如下:

 

 

說明static語句塊比構造方法執行的要早,我記得也是這樣的。那么,我就有了一個疑問,因為Driver中的static,要用到Driver的實現類,如果先執行static語句塊的話,不會拋出異常嗎?因為這個時候Driver的實現類還沒創建好啊

這里我犯了一個錯誤,就是誤認為構造方法執行完畢之后類才被創建,其實不是的,執行構造方法只是為了給類初始化,在執行構造方法只能類已經加載完畢,可以理解為類已經創建好了,所以是不會報錯的。

 

加載數據庫驅動推薦使用反射機制來創建Driver驅動的方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM