【JDBC】JDBC的Class.forName()存在的意义是什么?

JiongFoxi 2012-09-17 08:22:05
实在是找不到答案了,网上搜了一堆都没得到有用的信息。(=。=|XD不知道是不是我的关键字录入有问题)

SO。来CSDN,请教下各位大大。
近来复习之前的知识。在学习JDBC的时候。发现资料上说的是第一步需要加载驱动。
但是我把加载驱动那一行代码注释掉后。依然可以得到预期的数据。
所以,某就迷茫了。既然可有可无,那他存在的意义是什么?
我知道既然有这一步,那就就代表他一定是有用的。(=。=|理解不能呢。)

我猜想了一下。是不是利用反射机制,先把驱动类加载到内存中。
方便后续我们创建连接时对象的建立?

额。反射学的皮毛。可能理解的不够充分。

请各位大大赐教。。。
...全文
546 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
sky_08_06_02 2012-09-19
  • 打赏
  • 举报
回复
JDBC4自动加载合适的驱动
kky2010_110 2012-09-19
  • 打赏
  • 举报
回复
根据路径创建对象,一般路径就是“ss.xx.com.ClassName”,这个路径是可以任意改变的,总比new ss.xx.com.ClassName()来的方便吧,
emailshiyu 2012-09-18
  • 打赏
  • 举报
回复
你注释掉可以用和版本有关,以前的不行,写了保险
小傅哥 2012-09-18
  • 打赏
  • 举报
回复

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

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
JiongFoxi 2012-09-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

要用jdbc,首先要注册驱动的。相信楼主应该熟悉下面的方式,比如注册一个mysql的驱动:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());

那么Class.forName("com.mysql.jdbc.Driver");如果达到了上面的效果,是不是就可以理解了?
这句话是加载com.mysql.jdbc.Drive……
[/Quote]
T T。。。。。。
大大你好。我也清楚是加载驱动的。
额,最大的疑惑在于 为什么不用Class.forName 也可以达到预期的结果。。
JiongFoxi 2012-09-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

Class.forName("ClassName")
这一行代码的作用是把名字叫做ClassName的这个类加载到Java虚拟机里,加载后,就可以使用它来创建对象了。
[/Quote]
额。我有个疑惑就是,我不用Class。forName这一步。也可以达到我预期的效果。这是为什么呢?
加载驱动可有可无么?
还是说 默认(隐藏)的执行了加载驱动这一步骤
JiongFoxi 2012-09-18
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

Java code

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

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……
[/Quote]


谢谢前辈。了解了。
原来是因为新驱动,隐式的做了加载驱动这一步骤。
火光闪耀 2012-09-17
  • 打赏
  • 举报
回复
赞楼上啊,我一直只是会用,而不知道内部还是这样的。
brightyq 2012-09-17
  • 打赏
  • 举报
回复
要用jdbc,首先要注册驱动的。相信楼主应该熟悉下面的方式,比如注册一个mysql的驱动:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());

那么Class.forName("com.mysql.jdbc.Driver");如果达到了上面的效果,是不是就可以理解了?
这句话是加载com.mysql.jdbc.Driver.java的,看一下这个类的源码就知道了,在这个类的静态代码块是这样写的

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


看到了吗,和第一种方式一样的效果。
不光是mysql,sql server ,oracle的驱动都是类似的。
Inhibitory 2012-09-17
  • 打赏
  • 举报
回复
Class.forName("ClassName")
这一行代码的作用是把名字叫做ClassName的这个类加载到Java虚拟机里,加载后,就可以使用它来创建对象了。

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧