Java牛角尖【012】: JDBC開發時為什麼要用Class.forName(“”)

來源:互聯網
上載者:User

  前幾天看到一個文章中提出一個問題,在JDBC的開發中為什麼要使用Class.forName,可以不用這句嗎?

  我們從代碼出發,來分析一下這個問題。

  下面是一段我們常用的JDBC開發中的代碼(註:本文中例子使用Mysql為例子。為方便示範,代碼中忽略異常處理)

  Class.forName("com.mysql.jdbc.Driver");<br />conn = DriverManager.getConnection(<br />"jdbc:mysql://localhost:3306/mysql", "root", "");<br />stmt = conn.createStatement();<br />rs = stmt.executeQuery("select count(0) from user");<br />while (rs != null && rs.next()) {<br />System.out.println(rs.getInt(1));<br />}

  運行代碼,結果正常,列印出了Mysql資料庫中的使用者數。

  我們先嘗試將第一句拿掉,看是不是也可以運行。

  // 拿掉Class.forName語句,看一下運行結果<br />// Class.forName("com.mysql.jdbc.Driver");<br />conn = DriverManager.getConnection(<br />"jdbc:mysql://localhost:3306/mysql", "root", "");<br />stmt = conn.createStatement();<br />rs = stmt.executeQuery("select count(0) from user");<br />while (rs != null && rs.next()) {<br />System.out.println(rs.getInt(1));<br />}

  運行代碼,報如下錯誤:

  java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/mysql<br />at java.sql.DriverManager.getConnection(DriverManager.java:602)<br />at java.sql.DriverManager.getConnection(DriverManager.java:185)<br />at net.moon.jdbc.demo.Demo.main(Demo.java:18)

  看來是不行,那讓我們來分析一下,Class.forName(String clz)這樣一個方法到底做了什麼呢?

  看一下API,API中Class.forName方法的聲明如下:

  public static Class<?> forName(String className)<br /> throws ClassNotFoundException

  該方法是根據一個字串,得到這個字串所表示的類,但是我們上面代碼中並沒有一個引用指向這個返回的結果,也就是代碼並不關注返回的結果,那為什麼還要執行這句話呢,繼續往下看API中的說明,有這樣一句:“A call to forName("X") causes the class named X to be initialized”。

  問題似乎有點眉目了,原來在執行Class.forName("com.mysql.jdbc.Driver")這個語句時,com.mysql.jdbc.Driver這個類被初始化了,那一定是在初始化中做了什麼動作。為了證實這點,我們對上面的代碼做一點修改:

  // Class.forName("com.mysql.jdbc.Driver");<br />// 建立一個Driver對象,同樣不關注返回的結果<br />new com.mysql.jdbc.Driver();<br />conn = DriverManager.getConnection(<br />"jdbc:mysql://localhost:3306/mysql", "root", "");<br />stmt = conn.createStatement();<br />rs = stmt.executeQuery("select count(0) from user");<br />while (rs != null && rs.next()) {<br />System.out.println(rs.getInt(1));<br />}

  運行代碼,和預想的一樣,同樣可以得到運行結果。

  我們再來想一下,com.mysql.jdbc.Driver這個類在初始化的時候到底執行了什嗎?先來回憶一下以前的一篇文章:Java牛角尖【003】:類初始化時的執行順序。明白了,好像有這樣一個概念:靜態代碼塊。

  一定是在com.mysql.jdbc.Driver這個類中有一段靜態程式碼片段,這段代碼執行了某些動作。

  之所以用Mysql做為例子,還有另外一個優點,那就是開源,開源也就是說我們可以看到它的代碼,所以下個任務就是找到com.mysql.jdbc.Driver這個類的源碼來看一下了。

  代碼如下:

  static {<br />try {<br />java.sql.DriverManager.registerDriver(new Driver());<br />} catch (SQLException E) {<br />throw new RuntimeException("Can't register driver!");<br />}<br />}

  這段代碼似乎比我們想象的要簡單,是透過java.sql.DriverManager這個類的靜態方法registerDriver這個方法註冊這個JDBC驅動。

  最後一個問題就是為什麼這裡要調用registerDriver方法呢,那就是來看一下DrvierManager的API了,如下:

  registerDriver<br />public static void registerDriver(Driver driver)<br /> throws SQLException</p><p>向 DriverManager 註冊給定驅動程式。新載入的驅動程式類應該調用 registerDriver 方法讓 DriverManager 知道自己。 </p><p>參數:<br />driver - 將向 DriverManager 註冊的新的 JDBC Driver<br />拋出:<br />SQLException - 如果發生資料庫訪問錯誤

 

  上一篇: Java牛角尖【011】: Java中只支援單繼承嗎?

  下一篇:Java牛角尖【013】: finally塊中的代碼一定會執行嗎?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.