1. 程式人生 > >【解惑】JDBC中使用Class.forName("xxx")的意義

【解惑】JDBC中使用Class.forName("xxx")的意義

Class.forName方法介紹

在java.lang.Class中,有兩個過載的forName方法,分別是:

  1. static Class<?>(String className),該方法等價於Class.forName(className, true, this.getClass().getClassLoader())
  2. static Class<?>(String className, boolean initialize,ClassLoader loader),其中3個引數分別表示:className - 所需類的完全限定名,initialize - 是否必須初始化類,loader - 用於載入類的類載入器。

forName方法的作用就是:
使用給定的類載入器,返回與帶有給定字串名的類或介面相關聯的 Class 物件。給定一個類或介面的完全限定名,此方法會試圖定位、載入和連結該類或介面。指定的類載入器用於載入該類或介面,如果引數loader 為 null,則該類通過引導類載入器載入。只有 initialize 引數為 true且以前未被初始化時,才初始化該類。

其他的都很容易懂,就是當第二個引數為true時,到底初始化的是什麼呢?可以通過下面這個例子來了解:

  1. package wen.hui.test.forname;  
  2. /** 
  3.  * @author whwang 
  4.  * 
  5.  */
  6. public
    class TestClassForName {  
  7.     publicstaticvoid main(String[] args) throws ClassNotFoundException {  
  8.         (new TestClassForName()).loadClass();  
  9.     }  
  10.     @SuppressWarnings("unchecked")  
  11.     public Class<Test> loadClass() throws ClassNotFoundException {  
  12. //      Class<Test> clazz = (Class<Test>) Class.forName("wen.hui.test.forname.Test");
  13.         Class<Test> clazz = (Class<Test>) Class.forName("wen.hui.test.forname.Test"true, getClass().getClassLoader());  
  14.         return clazz;  
  15.     }  
  16. }  
  17. class Test {  
  18.     static {  
  19.         System.err.println("類的靜態初始化塊");  
  20.     }  
  21.     public Test() {  
  22.         System.err.println("例項化類");  
  23.     }  
  24. }  

執行後,列印:類的靜態初始化塊

沒錯,Class.forName的第二個引數為true時,就是要求JVM在載入類後,初始化類的靜態欄位和靜態塊。

JDBC中使用Class.forName("xxx")的意義

在Java開發特別是資料庫開發中,經常會用到Class.forName( )這個方法。通過上面的介紹,已經瞭解了Class.forName()方法的作用就是為了動態載入類,並決定是否需要初始化類的靜態部分,而在JDBC規範中明確要求Driver(資料庫驅動)類必須向DriverManager註冊自己。寫到這裡,相信大家都應該明白為什麼在我們載入資料庫驅動包的時候有的僅僅需要Class.forName(xxx);而有的需要Class.forName(xxx).newInstance()。

下面以MySQL為例子,來看看MySQL的com.mysql.jdbc.Driver類是怎麼寫的,MySQL的Driver類原始碼(5.x)

  1. publicclass Driver extends NonRegisteringDriver implements java.sql.Driver {  
  2.     // ~ Static fields/initializers
  3.     // ---------------------------------------------
  4.     //
  5.     // Register ourselves with the DriverManager
  6.     //
  7.     static {  
  8.         try {  
  9.             java.sql.DriverManager.registerDriver(new Driver());  
  10.         } catch (SQLException E) {  
  11.             thrownew RuntimeException("Can't register driver!");  
  12.         }  
  13.     }  
  14.     // ~ Constructors
  15.     // -----------------------------------------------------------
  16.     /** 
  17.      * Construct a new driver and register it with DriverManager 
  18.      *  
  19.      * @throws SQLException 
  20.      *             if a database error occurs. 
  21.      */
  22.     public Driver() throws SQLException {  
  23.         // Required for Class.forName().newInstance()
  24.     }  
  25. }  

在使用JDBC連線MySQL資料庫時,使用Class.forName("com.mysql.jdbc.Driver")就是為了向DriverManager註冊自己;當然使用Class.forName("com.mysql.jdbc.Driver").newInstance()當然也沒錯,只是沒有必要,因為後者還會生成Driver類的例項,而這個是我們沒有用的,沒有必要建立它。如果在Driver類中那個static塊裡面的部分寫在了構造方法中,那麼就必須使用Class.forName("com.mysql.jdbc.Driver").newInstance()來向DriverManager註冊了。