1. 程式人生 > >為什麼需要Class.forName("com.mysql.jdbc.Driver")

為什麼需要Class.forName("com.mysql.jdbc.Driver")

在使用傳統的JDBC連線資料庫的時候,總是需要這一句(以MySQL為例):

Class.forName("com.mysql.jdbc.Driver");  

以前我也沒深究,只是看網上的例子都這麼寫,實際上也跑通了,於是便懶得去管內部原理。不過大概還是清楚的,知道這句話是向DriverManage註冊了一個MySQL的JDBC Driver。

但為什麼要用Class.forName這樣看上去不是很優雅的方式呢?

網上還流傳了一個這樣的版本Class.forName("com.mysql.jdbc.Driver").newInstance(),似乎有點兒多此一舉。

經過實驗,我發現用com.mysql.jdbc.Driver driver = new

com.mysql.jdbc.Driver() 也是可以的,但是隻宣告

com.mysql.jdbc.Driver driver = null ,而不例項化卻又是不行的。

那麼Driver的註冊到底是在類的初始化時進行的,還是在類的物件初始化時進行的呢? 我也不知道,最好的辦法還是看原始碼:

package com.mysql.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

// Referenced classes of package com.mysql.jdbc:
//            NonRegisteringDriver

public class Driver extends NonRegisteringDriver
{

    public Driver()
        throws SQLException
    {
    }

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

原始碼之前沒祕密,com.mysql.jdbc.Driver很簡單,就是紅色的那句,看來是在類的static block裡面做的初始化。

那麼我們只要搞清楚在java裡面,static block執行的時機就可以清楚來龍去脈了。

還是做一個實驗吧:package com.javaye;

class A{
     static{
System.out.println("Class A loaded");
      }
     public A(){
System.out.println("create a instance of A");
      }
}

public class Main {
      public static void main(String[] args) throws Exception{
                 Class.forName("com.javaye.A");
     }
}

列印結果:“Class A loaded”

這說明Class.forName可以使類的static block中的程式碼得到執行。

然後,我們在修改成下面這樣:

package com.javaye;

class A{
static{
  System.out.println("Class A loaded");
}
public A(){
  System.out.println("create a instance of A");
}
}
public class Main {
public static void main(String[] args) throws Exception{
com.javaye.A a = null;
}
}

發現沒有列印任何東西,這說明只是宣告某個類的變數,是不會使static block的到執行的。

再改一下:

package com.javaye;

class A{
static{
  System.out.println("Class A loaded");
}
public A(){
  System.out.println("create a instance of A");
}
}
public class Main {
public static void main(String[] args) throws Exception{
com.javaye.A a = new com.javaye.A();
com.javaye.A a2 = new com.javaye.A();
}
}

輸出結果:

Class A loaded
create a instance of A
create a instance of A

這說明例項化一個類的話,static block 也會被執行,而且只會被執行一遍。

package data;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class MySql {
    private static String url="jdbc:mysql://127.0.0.1:3306/mydata";
    private static String user="test";
    private static String password="123";
    public static void main(String [] args)
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
        }
        catch (ClassNotFoundException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }// 載入驅動   
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = (Connection) DriverManager.getConnection(url, user, password);// 建立連線
            stmt = (Statement) conn.createStatement();

            String sql = "select * from role";
              rs = stmt.executeQuery(sql);

              while (rs.next()) {// 從結果集中取出資料
                     System.out.print(rs.getInt(1) + "/t");
                     System.out.print(rs.getString(2) + "/t");
                     System.out.print(rs.getString(3) + "/n");
              }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }// 執行sql語句

        System.out.println("Start to do it/n");
    }
}