java中Class.forName方法的作用詳解
前言
在做JAVA EE開(kāi)發(fā)的過(guò)程中,更多的是使用框架來(lái)提高開(kāi)發(fā)效率.越來(lái)越發(fā)現(xiàn),之前很基礎(chǔ)的一些東西,都忘記的差不多了.從今天開(kāi)始慢慢的復(fù)習(xí)一下基礎(chǔ).今天在看JDBC的時(shí)候,就有一個(gè)有趣的地方,之前學(xué)的時(shí)候,也沒(méi)在意.這個(gè)Class.forName
究竟是什么鬼.
連接數(shù)據(jù)庫(kù)幾大步.看以下代碼
import com.mysql.jdbc.Driver; import java.sql.*; /** * @author honway.liu * @date 2016/12/8 下午11:07 * @email gm100861@gmail.com * @blog http://linuxsogood.org */ public class JdbcDemo { public static void main(String[] args) throws SQLException, ClassNotFoundException { String url = "jdbc:mysql://127.0.0.1:3306/mydb"; String username = "root"; String password = "redhat"; Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); String sql = "SELECT * FROM msg"; PreparedStatement prepareStatement = connection.prepareStatement(sql); ResultSet resultSet = prepareStatement.executeQuery(); resultSet.next(); String address = resultSet.getString("address"); System.out.println(address); } }
其中第一步,搞的我有點(diǎn)想不通.為啥Class.forName
傳入了一段字符串之后,就知道我連接的數(shù)據(jù)庫(kù)是mysql? 有點(diǎn)不科學(xué)啊.Class.forName
到底做了啥.下面就開(kāi)始到源碼中,一探究竟.
@CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }
發(fā)現(xiàn)它調(diào)用了forName0
方法,繼續(xù)跟蹤再看看
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
native
方法,源碼也只能到此結(jié)束了.看下官方文檔,怎么說(shuō)吧.
https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)
發(fā)現(xiàn)官方文檔,還是描述的很清楚的.
Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the parameter loader is null, the class is loaded through the bootstrap class loader. The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.
嗯,描述的還算是很清楚.返回一個(gè)給定類(lèi)或者接口的一個(gè)Class
對(duì)象,如果沒(méi)有給定classloader
,那么會(huì)使用根類(lèi)加載器.如果initalize
這個(gè)參數(shù)傳了true
,那么給定的類(lèi)如果之前沒(méi)有被初始化過(guò),那么會(huì)被初始化.我們?cè)贘DBC第一步的時(shí)候,傳入的參數(shù)是com.mysql.jdbc.Driver
. 也就是說(shuō)這個(gè)類(lèi)會(huì)被初始化.我們看一下這個(gè)類(lèi)里面的內(nèi)容.
public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } public Driver() throws SQLException { // Required for Class.forName().newInstance() } }
我們發(fā)現(xiàn)這個(gè)類(lèi)也是超級(jí)簡(jiǎn)單的.一個(gè)構(gòu)造函數(shù)和一個(gè)靜態(tài)代碼塊.我們知道,類(lèi)在初始化的時(shí)候,靜態(tài)代碼塊的內(nèi)容會(huì)被執(zhí)行的.也就是說(shuō)我們Class.forName
和直接寫(xiě)DriverManager.registerDriver(new Driver)
兩者功能是等同的.我們換成這種寫(xiě)法.再試試看.
public class JdbcDemo { public static void main(String[] args) throws SQLException, ClassNotFoundException { String url = "jdbc:mysql://127.0.0.1:3306/mydb"; String username = "root"; String password = "redhat"; //Class.forName("com.mysql.jdbc.Driver"); DriverManager.registerDriver(new Driver()); Connection connection = DriverManager.getConnection(url, username, password); String sql = "SELECT * FROM msg"; PreparedStatement prepareStatement = connection.prepareStatement(sql); ResultSet resultSet = prepareStatement.executeQuery(); resultSet.next(); String address = resultSet.getString("address"); System.out.println(address); } }
發(fā)現(xiàn)代碼,還是正常的執(zhí)行了.
總結(jié)一下:
Class.forName
方法的作用,就是初始化給定的類(lèi).而我們給定的MySQL的Driver類(lèi)中,它在靜態(tài)代碼塊中通過(guò)JDBC的DriverManager
注冊(cè)了一下驅(qū)動(dòng).我們也可以直接使用JDBC的驅(qū)動(dòng)管理器注冊(cè)mysql驅(qū)動(dòng).從而代替使用Class.forName
.
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
springboot中.yml文件的值無(wú)法讀取的問(wèn)題及解決
這篇文章主要介紹了springboot中.yml文件的值無(wú)法讀取的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02使用JPA進(jìn)行CriteriaQuery進(jìn)行查詢(xún)的注意事項(xiàng)
這篇文章主要介紹了使用JPA進(jìn)行CriteriaQuery進(jìn)行查詢(xún)的注意事項(xiàng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12關(guān)于@Autowierd && @Resource 你真的了解嗎
這篇文章主要介紹了關(guān)于@Autowierd && @Resource的具體使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08SpringBoot項(xiàng)目整合Redis教程詳解
這篇文章主要介紹了SpringBoot項(xiàng)目整合Redis教程詳解,Redis?是完全開(kāi)源的,遵守?BSD?協(xié)議,是一個(gè)高性能的?key-value?數(shù)據(jù)庫(kù)。感興趣的小伙伴可以參考閱讀本文2023-03-03關(guān)于QueryWrapper高級(jí)使用示例
本文介紹了QueryWrapper的高級(jí)使用方法,包括查詢(xún)指定字段、使用MySQL函數(shù)處理字段、設(shè)置查詢(xún)限制等,通過(guò)select()可查詢(xún)指定字段并處理,last()方法實(shí)現(xiàn)limit效果,apply()可在查詢(xún)條件中使用函數(shù),這些技巧有助于提升數(shù)據(jù)庫(kù)操作的靈活性和效率2024-09-09Resty開(kāi)發(fā)restful版本的Jfinal深入研究
這篇文章主要為大家介紹了Resty開(kāi)發(fā)restful版本的Jfinal深入研究有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03