java中class.forname连接mysql数据库_数据库链接与 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(); 是一樣的效果。
現在言歸正傳。
動態加載和創建Class 對象,比如想根據用戶輸入的字符串來創建對象時需要用到:
String str = “用戶輸入的字符串” ;
Class t = Class.forName(str);
t.newInstance();
在初始化一個類,生成一個實例的時候,newInstance()方法和new關鍵字除了一個是方法,一個是關鍵字外,最主要有什么區別?它們的區別在于創建對象的方式不一樣,前者是使用類加載機制,后者是創建一個新類。那么為什么會有兩種創建對象方式?這主要考慮到軟件的可伸縮、可擴展和可重用等軟件設計思想。
Java中工廠模式經常使用newInstance()方法來創建對象,因此從為什么要使用工廠模式上可以找到具體答案。 例如:
class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();
其中ExampleInterface是Example的接口,可以寫成如下形式:
String className = “Example”;
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
進一步可以寫成如下形式:
String className = readfromXMlConfig;//從xml 配置文件中獲得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
上面代碼已經不存在Example的類名稱,它的優點是,無論Example類怎么變化,上述代碼不變,甚至可以更換Example的兄弟類Example2 , Example3 , Example4……,只要他們繼承ExampleInterface就可以。
從JVM的角度看,我們使用關鍵字new創建一個類的時候,這個類可以沒有被加載。但是使用newInstance()方法的時候,就必須保證:
1、這個類已經加載;
2、這個類已經連接了。
而完成上面兩個步驟的正是Class的靜態方法forName()所完成的,這個靜態方法調用了啟動類加載器,即加載 JavaAPI的那個加載器。
現在可以看出,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( )是動態加載類是沒有用的,其最終目的是為了實例化對象。
有數據庫開發經驗朋友會發現,為什么在我們加載數據庫驅動包的時候有的卻沒有調用newInstance( )方法呢?
即有的jdbc連接數據庫的寫法里是Class.forName(xxx.xx.xx);而有一 些:Class.forName(xxx.xx.xx).newInstance(),為什么會有這兩種寫法呢?
剛才提到,Class.forName(“”);的作用是要求JVM查找并加載指定的類,首先要明白,java里面任何class都要裝載在虛擬機上才能運行,而靜態代碼是和class綁定的,class裝載成功就表示執行了你的靜態代碼了,而且以后不會再走這段靜態代碼了。
而我們前面也說了,Class.forName(xxx.xx.xx)的作用就是要求JVM查找并加載指定的類,如果在類中有靜態初始化器的話,JVM必然會執行該類的靜態代碼段。
而在JDBC規范中明確要求這個Driver類必須向DriverManager注冊自己,即任何一個JDBC Driver的 Driver類的代碼都必須類似如下:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}
既然在靜態初始化器的中已經進行了注冊,所以我們在使用JDBC時只需要Class.forName(XXX.XXX);就可以了。
相關英文參考文獻如下:
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.
//第一步:在靜態代碼塊中,直接加載數據庫的驅動//加載驅動,不是直接簡單的使用com.mysql.jdbc.Driver就可以了//之所以說,不要硬編碼,他的原因就在于這里 com.mysql.jdbc.Driver只代表了MySQL數據庫的驅動//那么,如果有一天,我們的項目底層的數據庫要進行遷移,比如遷移到Oracle//或者是DB2、SQLServer//那么,就必須很費勁的在代碼中,找,找到硬編碼了com.mysql.jdbc.Driver的地方,然后改成//其他數據庫的驅動類的類名//所以正規項目,是不允許硬編碼的,那樣維護成本很高通常,我們都是用一個常量接口中的某個常量,來代表一個值//然后在這個值改變的時候,只要改變常量接口中的常量對應的值就可以了項目,要盡量做成可配置的//就是說,我們的這個數據庫驅動,更進一步,也不只是放在常量接口中就可以了//最好的方式,是放在外部的配置文件中,跟代碼徹底分離//常量接口中,只是包含了這個值對應的key的名字
Class轉載的時候 本靜態代碼已經加載到jvm 里面 了 ,所以就不需要在instance 了
static{
try{
String driver = ConfigurationManager.getProperty(Constants.JDBC_DRIVER);Class.forName(driver);} catch(Exception e) {
e.printStackTrace();}
}
總結
以上是生活随笔為你收集整理的java中class.forname连接mysql数据库_数据库链接与 Class.forName()用法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java泛型怎么用反射生成_Java 之
- 下一篇: java死循环_java小白关于whil