Class.forName()用法詳解

主要功能
Class.forName(xxx.xx.xx)返回的是一個類。
Class.forName(xxx.xx.xx)的做用是要求JVM查找並加載指定的類,也就是說JVM會執行該類的靜態代碼段。

下面,經過解答如下三個問題的來詳細講解下Class.forName()的用法。
一.何時用Class.forName()?
先來個熱身,給你一個字符串變量,它表明一個類的包名和類名,你怎麼實例化它?你第一想到的確定是new,可是注意一點:
A a = (A)Class.forName(「pacage.A」).newInstance();
這和你 A a = new A(); 是同樣的效果。html

如今言歸正傳。
動態加載和建立Class 對象,好比想根據用戶輸入的字符串來建立對象時須要用到:
String str = 「用戶輸入的字符串」 ;
Class t = Class.forName(str);
t.newInstance();java

在初始化一個類,生成一個實例的時候,newInstance()方法和new關鍵字除了一個是方法,一個是關鍵字外,最主要有什麼區別?數據庫

它們的區別在於建立對象的方式不同,前者是使用類加載機制,後者是建立一個新類。jvm

那麼爲何會有兩種建立對象方式?這主要考慮到軟件的可伸縮、可擴展和可重用等軟件設計思想。函數

Java中工廠模式常用newInstance()方法來建立對象,所以從爲何要使用工廠模式上能夠找到具體答案。 例如:
class c = Class.forName(「Example」);
factory = (ExampleInterface)c.newInstance();post

其中ExampleInterface是Example的接口,能夠寫成以下形式:
String className = 「Example」;
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();ui

進一步能夠寫成以下形式:
String className = readfromXMlConfig;//從xml 配置文件中得到字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();編碼

上面代碼已經不存在Example的類名稱,它的優勢是,不管Example類怎麼變化,上述代碼不變,甚至能夠更換Example的兄弟類Example2 , Example3 , Example4……,只要他們繼承ExampleInterface就能夠。url

從JVM的角度看,咱們使用關鍵字new建立一個類的時候,這個類能夠沒有被加載。可是使用newInstance()方法的時候,就必須保證:
一、這個類已經加載;
二、這個類已經鏈接了。
而完成上面兩個步驟的正是Class的靜態方法forName()所完成的,這個靜態方法調用了啓動類加載器,即加載 java API的那個加載器。設計

如今能夠看出,newInstance()其實是把new這個方式分解爲兩步,即首先調用Class加載方法加載某個類,而後實例化。

這樣分步的好處是顯而易見的。咱們能夠在調用class的靜態加載方法forName時得到更好的靈活性,提供給了一種降耦的手段。

二.new 和Class.forName()有什麼區別?
其實上面已經說到一些了,這裏來作個總結:
首先,newInstance( )是一個方法,而new是一個關鍵字;
其次,Class下的newInstance()的使用有侷限,由於它生成對象只能調用無參的構造函數,而使用 new關鍵字生成對象沒有這個限制。
簡言之:
newInstance(): 弱類型,低效率,只能調用無參構造。
new: 強類型,相對高效,能調用任何public構造。
Class.forName(「」)返回的是類。
Class.forName(「」).newInstance()返回的是object 。
三.爲何在加載數據庫驅動包的時候有用的是Class.forName( ),卻沒有調用newInstance( )?
在Java開發特別是數據庫開發中,常常會用到Class.forName( )這個方法。
經過查詢Java Documentation咱們會發現使用Class.forName( )靜態方法的目的是爲了動態加載類。
一般編碼過程當中,在加載完成後,通常還要調用Class下的newInstance( )靜態方法來實例化對象以便操做。所以,單使用Class.forName( )是動態加載類是沒有用的,其最終目的是爲了實例化對象。

相關英文參考文獻以下:
we just want to load the driver to jvm only, but not need to user the instance of driver,
so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(),
the result will same as calling Class.forName(xxx.xx.xx),
because Class.forName(xxx.xx.xx).newInstance() will load driver first,
and then create instance, but the instacne you will never use in usual,
so you need not to create it.

========================== 分割線 =============================

Class.forName()、Class.forName().newInstance() 、New 三者區別!

 

   在Java開發特別是數據庫開發中,常常會用到Class.forName( )這個方法。
經過查詢Java Documentation咱們會發現使用Class.forName( )靜態方法的目的是爲了動態加載類。
在加載完成後,通常還要調用Class下的newInstance( )靜態方法來實例化對象以便操做。所以,單單使用Class.forName( )是動態加載類是沒有用的,其最終目的是爲了實例化對象。 
   這裏有必要提一下就是Class下的newInstance()和new有什麼區別?,首先,newInstance( )是一個方法,而new是一個關鍵字,其次,Class下的newInstance()的使用有侷限,由於它生成對象只能調用無參的構造函數,而使用 new關鍵字生成對象沒有這個限制。 
   好,到此爲止,咱們總結以下: 
   Class.forName("")返回的是類 
   Class.forName("").newInstance()返回的是object 
   有數據庫開發經驗朋友會發現,爲何在咱們加載數據庫驅動包的時候有的卻沒有調用newInstance( )方法呢?即有的jdbc鏈接數據庫的寫法裏是Class.forName(xxx.xx.xx);而有一 些:Class.forName(xxx.xx.xx).newInstance(),爲何會有這兩種寫法呢?
   剛纔提到,Class.forName("");的做用是要求JVM查找並加載指定的類,若是在類中有靜態初始化器的話,JVM必然會執行該類的靜態代碼 段。而在JDBC規範中明確要求這個Driver類必須向DriverManager註冊本身,即任何一個JDBC Driver的 Driver類的代碼都必須相似以下:
  public class MyJDBCDriver implements Driver {
   static {
     DriverManager.registerDriver(new MyJDBCDriver());
  }
  }
 既然在靜態初始化器的中已經進行了註冊,因此咱們在使用JDBC時只須要Class.forName(XXX.XXX);就能夠了。
 
貼出Proxool 鏈接池的靜態初始化方法:
public class ProxoolDriver implements Driver {

    private static final Log LOG = LogFactory.getLog(ProxoolDriver.class);

    static {
        try {
            DriverManager.registerDriver(new ProxoolDriver());
        } catch (SQLException e) {
            System.out.println(e.toString());
        }
    }
}
相關文章
相關標籤/搜索