JDBC在getConnection之前为什么要调用Class.forName(转)

简介: 获取一个数据库连接的通用模板如下: String driver = "oracle.jdbc.OracleDriver"; String url = "jdbc:oracle:thin:@127.

获取一个数据库连接的通用模板如下:

String driver = "oracle.jdbc.OracleDriver" ;
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl" ;
String user = "scott" ;
String password = "ticmy" ;
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);

里面有个Class.forName(driver),这句话有什么作用?将驱动类load到内存?如果没有这句会怎么样?运行发现,如果去掉这一句会有以下异常:
java.sql.SQLException: No suitable driver found for xxx….

在解释具体原因之前先简单看下Class.forName做了什么。

假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情:
1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象
2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系)
3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static块。(这一步是要点)

Class.forName(String className)方法会将这三步都做掉,如下面的例子:

package com.ticmy.oracle;
 
public class TestClinit {
     public static void main(String[] args) throws Exception {
         Class.forName( "com.ticmy.oracle.ABC" );
     }
}
class ABC {
     private static int a = getNum();
     static {
         System.out.println( "this is static block" );
     }
     public static int getNum() {
         System.out.println( "getNum" );
         return 1 ;
     }
}

程序的运行结果是:
getNum
this is static block

那么,Class.forName(driver)这个driver类里有没有什么static块呢?去探究一下。例子用的是Oracle,反编译下oracle.jdbc.OracleDriver,发现其继承了oracle.jdbc.driver.OracleDriver,那么继续看这个oracle.jdbc.driver.OracleDriver,确实有个static块,里面有这样的代码:

static {
     Timestamp localTimestamp = Timestamp.valueOf( "2000-01-01 00:00:00.0" );
     try {
       if (defaultDriver == null ) {
         defaultDriver = new OracleDriver();
         DriverManager.registerDriver(defaultDriver);
       }
     } catch (RuntimeException localRuntimeException) {
     } catch (SQLException localSQLException){}
     _Copyright_2004_Oracle_All_Rights_Reserved_ = null ;
}

再看看mysql吧:com.mysql.jdbc.Driver:
同样发现了static块,里面代码如下:

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

再看一个db2:com.ibm.db2.jcc.DB2Driver:
也发现了static块:

static {
     if (o.Nb != null ) {
       exceptionsOnLoadDriver__ = dg.a(o.Nb, exceptionsOnLoadDriver__);
     }
 
     try {
       registeredDriver__ = new DB2Driver();
       DriverManager.registerDriver(registeredDriver__);
     }
     catch (SQLException localSQLException) {
       exceptionsOnLoadDriver__ = new SqlException( null ,
       "Error occurred while trying to register Jcc driver with JDBC 1 Driver Manager" );
       exceptionsOnLoadDriver__.setNextException(localSQLException);
     }
}

无一例外地,发现里面都有DriverManager.registerDriver(driver)的调用。那么是不是可以将开头的例子中的Class.forName换成DriverManager.registerDriver呢?

String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl" ;
String user = "scott" ;
String password = "ticmy" ;
DriverManager.registerDriver( new OracleDriver());
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
conn.close();

经过测试发现OK。现在,已经知道Class.forName(driver)的根本目的就是为了调用DriverManager.registerDriver。

Class.forName还有个重载的方法:Class.forName(String name, boolean initialize, ClassLoader loader),Class.forName(String className)就等价于Class.forName(className, true, currentLoader),注意中间的参数为true,这个参数的含义就是要不要初始化。如果此参数为true且指定的类以前没有被初始化过,就会去初始化。

另外,jdbc4已经不需要显式的调用Class.forName了,在jdbc4中,调用getConnection的时候DriverManager会自动去加载合适的驱动。
http://www.ticmy.com/?p=249

相关文章
|
Java 数据库连接 数据库
JDBC学习(三):封装工具类JDBCUtils类
为了以后方便进行数据库连接、数据库关闭、还有后面的连接池的操作等功能,现在将功能封装到JDBCUtils类当中,作为自己的一个工具箱。
342 0
|
28天前
|
Java
Class.forName和ClassLoader到底有啥区别
Class.forName和ClassLoader到底有啥区别
12 0
|
6月前
|
SQL Java 数据库连接
深入理解 JDBC:Java 数据库连接详解
数据库是现代应用程序的核心组成部分之一。无论是 Web 应用、移动应用还是桌面应用,几乎都需要与数据库交互以存储和检索数据。Java 提供了一种强大的方式来实现与数据库的交互,即 JDBC(Java 数据库连接)。本文将深入探讨 JDBC 的各个方面,从基本概念到实际编程示例,以帮助您理解和使用 JDBC。
364 2
|
8月前
|
Java 数据库连接
Java 中封装JDBC连接到JDBCUtils工具类的详解
Java 中封装JDBC连接到JDBCUtils工具类的详解
41 0
|
11月前
|
SQL Java 关系型数据库
JDBC系列-详解各个对象
JDBC系列-详解各个对象
53 0
|
Java 数据库连接 API
Java“ Class.forName()”和“ Class.forName()newInstance()”之间有什么区别?
Java“ Class.forName()”和“ Class.forName()newInstance()”之间有什么区别?
|
SQL Java 数据库连接
【JDBC】JDBCUtils工具类开发
1.JDBCUtils工具类开发 我们来写一个Jdbc工具类——JdbcUtils,这个工具类可以用来获取Connection对象以及关闭数据库连接 上代码:
125 0
|
SQL Oracle Java
|
关系型数据库 数据库 PostgreSQL
DriverManager.registerDriver(new Driver());与Class.forName(“com.mysql.jdbc.Driver”);的区别
DriverManager.registerDriver(new Driver());与Class.forName(“com.mysql.jdbc.Driver”);的区别
241 0
|
前端开发 Java 关系型数据库
Class.forName 和 ClassLoader 到底有啥区别?
Class.forName 和 ClassLoader 到底有啥区别?
108 0