- 浏览: 310533 次
- 性别:
- 来自: 广州/成都
最新评论
-
lgh1992314:
Godlikeme 写道<div class='quot ...
使用JDBC时Class.forName()的作用 -
lgh1992314:
Class.forName("com.mysql.j ...
使用JDBC时Class.forName()的作用 -
sandaobusi:
nkd2002 写道“我们完全可以用这样一句代替它:”博主这名 ...
使用JDBC时Class.forName()的作用 -
nkd2002:
“我们完全可以用这样一句代替它:”博主这名句话有错误,第二段代 ...
使用JDBC时Class.forName()的作用 -
topcoder_lin:
写的很好!!!!
使用JDBC时Class.forName()的作用
使用JDBC时,我们都会很自然得使用下列语句:
- Class.forName("com.mysql.jdbc.Driver");
- String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";
- String user = "";
- String psw = "";
- Connection con = DriverManager.getConnection(url,user,psw);
为什么说很自然呢,因为无论是网上还是书本教程上得例子都是这样的,而且程序也确实正常运行了,于是大家也就心安理得的找葫芦画瓢下去了。
一定要有这一句吗?不是的,我们完全可以用这样一句代替它:
- com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
- //or:
- //new com.mysql.jdbc.Driver();
- String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";
- String user = "";
- String psw = "";
- Connection con = DriverManager.getConnection(url,user,psw);
大家可能都看出个大概来了,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。上面两种方法都可以实现这个功能,因此程序可以正常运行。注意了,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。
- com.mysql.jdbc.Driver driver = null;
- //or:
- ClassLoader cl = new ClassLoader();
- cl.loadClass("com.mysql.jdbc.Driver");
我们都知道JDBC是使用Bridge模式进行设计的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现(请参考GOF的Bridge模式的描述)。大家注意了,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。
Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去啊,这是怎么回事呢?jdk文档对Driver的描述中有这么一句:
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager
哦,原来是com.mysql.jdbc.Driver在装载完后自动帮我们完成了这一步骤。源代码是这样的:
- package com.mysql.jdbc
- public class Driver extends NonRegisteringDriver implements java.sql.Driver {
- // ~ Static fields/initializers
- // --------------------------------------------- //
- // Register ourselves with the DriverManager
- //
- static {
- t ry {
- java.sql.DriverManager.registerDriver(new Driver());
- } catch (SQLException E) {
- throw new RuntimeException("Can't register driver!");
- }
- }
- // ~ Constructors
- // -----------------------------------------------------------
- /**
- * Construct a new driver and register it with DriverManager
- *
- * @throws SQLException
- * if a database error occurs.
- */
- public Driver() throws SQLException {
- // Required for Class.forName().newInstance()
- }
- }
评论
<p>to 楼上的楼上 Class.forName和 ClassLoader.loadClass是两码事,一个实例化类,一个加载类,不好混到一起说。</p>
</div>
Class.forName(className)方法,内部实际调用的方法是 Class.forName(className,true,classloader);
第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。
一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。
ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false);
第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,
不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行
压根就可以不加
博主这名句话有错误,第二段代码不能代替第一段,原因请参考http://www.ibm.com/developerworks/cn/java/j-lo-classloader/
第二段理论上不能代替第一段,但是在这种情况下是可以代替的。只要执行了static块就好
博主这名句话有错误,第二段代码不能代替第一段,原因请参考http://www.ibm.com/developerworks/cn/java/j-lo-classloader/
hello world! 说的太棒了!
<p>to 楼上的楼上 Class.forName和 ClassLoader.loadClass是两码事,一个实例化类,一个加载类,不好混到一起说。</p>
</div>
<strong>Dustin 写道:</strong><br/>
<div class='quote_div'>
<p> 使用JDBC时,我们都会很自然得使用下列语句:</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span>Class.forName(</span><span class='string'>"com.mysql.jdbc.Driver"</span><span>); </span></span> </li>
<li class=''><span>String url = </span><span class='string'>"jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8"</span><span>; </span> </li>
<li class='alt'><span>String user = </span><span class='string'>""</span><span>; </span> </li>
<li class=''><span>String psw = </span><span class='string'>""</span><span>; </span> </li>
<li class='alt'><span>Connection con = DriverManager.getConnection(url,user,psw); </span> </li>
</ol>
</div>
<p><br/>
为什么说很自然呢,因为无论是网上还是书本教程上得例子都是这样的,而且程序也确实正常运行了,于是大家也就心安理得的找葫芦画瓢下去了。<br/>
一定要有这一句吗?不是的,我们完全可以用这样一句代替它:<br/>
</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span>com.mysql.jdbc.Driver driver = </span><span class='keyword'>new</span><span> com.mysql.jdbc.Driver(); </span></span> </li>
<li class=''><span/><span class='comment'>//or: </span><span> </span> </li>
<li class='alt'><span/><span class='comment'>//new com.mysql.jdbc.Driver(); </span><span> </span> </li>
<li class=''><span>String url = </span><span class='string'>"jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8"</span><span>; </span> </li>
<li class='alt'><span>String user = </span><span class='string'>""</span><span>; </span> </li>
<li class=''><span>String psw = </span><span class='string'>""</span><span>; </span> </li>
<li class='alt'><span>Connection con = DriverManager.getConnection(url,user,psw); </span> </li>
<li class=''><span> </span> </li>
</ol>
</div>
<br/>
<p> 大家可能都看出个大概来了,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。上面两种方法都可以实现这个功能,因此程序可以正常运行。注意了,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span>com.mysql.jdbc.Driver driver = </span><span class='keyword'>null</span><span>; </span></span> </li>
<li class=''><span/><span class='comment'>//or: </span><span> </span> </li>
<li class='alt'><span>ClassLoader cl = </span><span class='keyword'>new</span><span> ClassLoader(); </span> </li>
<li class=''><span>cl.loadClass(</span><span class='string'>"com.mysql.jdbc.Driver"</span><span>); </span> </li>
</ol>
</div>
<p><br/>
我们都知道JDBC是使用Bridge模式进行设计的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现(请参考GOF的Bridge模式的描述)。大家注意了,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。<br/>
Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去啊,这是怎么回事呢?jdk文档对Driver的描述中有这么一句:<br/>
<strong>When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager <br/>
</strong>哦,原来是com.mysql.jdbc.Driver在装载完后自动帮我们完成了这一步骤。源代码是这样的:</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
<li class='alt'><span><span class='keyword'>package</span><span> com.mysql.jdbc </span></span> </li>
<li class=''><span> </span> </li>
<li class='alt'><span/><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> Driver </span><span class='keyword'>extends</span><span> NonRegisteringDriver </span><span class='keyword'>implements</span><span> java.sql.Driver { </span> </li>
<li class=''><span> </span><span class='comment'>// ~ Static fields/initializers </span><span> </span> </li>
<li class='alt'><span> </span><span class='comment'>// --------------------------------------------- // </span><span> </span> </li>
<li class=''><span> </span><span class='comment'>// Register ourselves with the DriverManager </span><span> </span> </li>
<li class='alt'><span> </span><span class='comment'>// </span><span> </span> </li>
<li class=''><span> </span><span class='keyword'>static</span><span> { </span> </li>
<li class='alt'><span> t ry { </span> </li>
<li class=''><span> java.sql.DriverManager.registerDriver(</span><span class='keyword'>new</span><span> Driver()); </span> </li>
<li class='alt'><span> } </span><span class='keyword'>catch</span><span> (SQLException E) { </span> </li>
<li class=''><span> </span><span class='keyword'>throw</span><span> </span><span class='keyword'>new</span><span> RuntimeException(</span><span class='string'>"Can't register driver!"</span><span>); </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span> } </span> </li>
<li class='alt'><span/><span class='comment'>// ~ Constructors </span><span> </span> </li>
<li class=''><span> </span><span class='comment'>// ----------------------------------------------------------- </span><span> </span> </li>
<li class='alt'><span/><span class='comment'>/** </span> </li>
<li class=''><span><span class='comment'> * Construct a new driver and register it with DriverManager </span> </span> </li>
<li class='alt'><span><span class='comment'> * </span> </span> </li>
<li class=''><span><span class='comment'> * @throws SQLException </span> </span> </li>
<li class='alt'><span><span class='comment'> * if a database error occurs. </span> </span> </li>
<li class=''><span><span class='comment'> */</span><span> </span></span> </li>
<li class='alt'><span> </span><span class='keyword'>public</span><span> Driver() </span><span class='keyword'>throws</span><span> SQLException { </span> </li>
<li class=''><span> </span><span class='comment'>// Required for Class.forName().newInstance() </span><span> </span> </li>
<li class='alt'><span> } </span> </li>
<li class=''><span>} </span> </li>
</ol>
</div>
</div>
<p><br/>
这里ClassLoader为什么不行,是类加载器的机制决定的 <a href='http://www.iteye.com/topic/25053'>www.iteye.com/topic/25053<strong/></a></p>
<p><strong>static块在什么时候执行?</strong> <br/>
1)当调用forName(String)载入class时执行,如果调用ClassLoader.loadClass并不会执行.forName(String,false,ClassLoader)时也不会执行. <br/>
2)如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作 <br/>
3)static块仅执行一次</p>
<p><br/>
<br/>
<br/>
</p>
complystill从宏观上道出了Class.forName()的作用,我主要是从微观上进行考量的
非M$系的书上和文章里多数这样写,应该因为是从读配置文件初始化JDBC的代码简化来的.
M$系的文章和教材经常是 Driver d = new XXXDriver(); 多半是保证Vendor-Lockin的传统习俗.
发表评论
-
Linux内存管理
2011-05-21 23:42 2441首先提供Gustavo Duarte写的三篇非常精彩的文章: ... -
RSA算法密钥长度的选择
2010-09-15 15:07 16654RSA算法密钥长度的选择是安全性和程序性能平衡的结果,密钥 ... -
Python code snip
2009-10-28 22:22 1827Python Tips, Tricks, and Hacks ... -
C++ code snip
2009-08-23 18:01 18371. 将文件内容读取为string a. s ... -
多重继承和Mixin
2009-04-06 22:46 01. c++多重继承 http://www.newlc.com ... -
使用DataSource的连接池何以提高性能?
2009-04-06 22:03 1955最初发表在这里。 连接池为什么能够提高性能呢? ... -
1.03 - 0.42 = ?
2009-04-06 21:45 1537最初发表在这里。 0.6 ... -
C/C++库文件简介
2009-04-06 21:25 2728最初发表在这里。 ... -
多态(Polymorphism)的实现机制(下)--Java篇
2009-04-06 21:14 3291最初发表在这里。 ... -
多态(Polymorphism)的实现机制(上)--C++篇
2009-04-06 20:48 3882最初发表在这里。 多态(Polymorph ... -
awk引用shell中带meta字符的字符串
2009-03-25 20:45 2164link='http://localhost:8080 Blo ... -
Two extractors couldn't work together
2008-01-12 01:32 1593Hi,everyone I have enjoyed Scr ... -
C++的常量
2007-05-31 11:20 1672Java里面使用常量十分方便,将成员变量定义为fina ... -
Python中文问题研究
2007-05-07 18:30 10912我曾经在深入浅出java中文问题系列中研究过java的中文 ... -
深入浅出Java中文问题(六) 文件读写
2007-05-07 17:16 8188最近用Java处理文 ... -
深入浅出java中文问题(五)数据库出现的中文问题
2007-05-07 17:14 3893数据库的重要作用无需多言,java也为我们提供了多种数据 ... -
深入浅出java中文问题(四)Web应用中的中文问题
2007-05-07 17:12 2823Web应用中出现的中 ... -
深入浅出java中文问题(三)console程序的中文问题
2007-05-07 17:08 4484现代计算机采用的 ... -
深入浅出Java中文问题(二)字符,字节和编码
2007-05-07 17:03 4765通过引言我们可以 ... -
深入浅出Java中文问题(一) 引言
2007-05-07 16:59 3331真正接触过java,或 ...
相关推荐
主要介绍了jdbc中class.forname的作用,使用示例说明了他作用及使用方法,大家参考使用吧
jdbc-odbc驱动包,提示找不到驱动,java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver, 原因:从jdk从1.8开始,删除了jdbc-odbc桥,所以odbc的驱动是用不了的 解决方法:这里为提供一个解决JDK1.8不...
主要介绍了使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")的相关知识,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
java连接各种数据库的驱动 jar包 orale: Class.forName("oracle.jdbc.driver.OracleDriver"); mysql:Class.forName("com.mysql.jdbc.Driver"); access:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); sqlsever:...
//或者Class.forName("com.mysql.jdbc.Driver"); String url ="jdbc:mysql://localhost/myDB? user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" //myDB为数据库名 Connection conn= ...
对SPI,理论联系实际的理解
jdbc连接jdbc.class 可用于记事版 与数据库连接
如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据Class.forName (com.mysql.jdbc.Driver); public static Connection getConnection() throws ClassNotFoundException, SQLException ...
java链接sqlserver数据库包如下错误时: java.lang.ClassNotFoundException: ... at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) 添加sqljdbc4-2.0包即可
Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000 数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2 数据库 Class.froName(...
at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at com.trs.gateway.commons.hive.HiveFeature.getConnection(HiveFeature.java:55) ... 8 more
Class.forName( "oracle.jdbc.driver.OracleDriver" ); con = DriverManager.getConnection( "jdbc:oracle:thin:@127.0.0.1:1521:ORCL", "scott", ”tiger”); 连接SqlServer2000 msbase.jar ...
其中classes12.jar是从oracle安装目录中获取的,使用它编写java程序连接oracle时,驱动包的加载路径为"oracle.jdbc.driver.OracleDriver",即Class.forName("oracle.jdbc.driver.OracleDriver")。另一个ojdbc6.jar的...
Java连接SQL server数据库驱动,文件包含sqljdb和sqljdbc4 ...sqljdbc:Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); sqljdbc4:Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
使用JDBC-ODBC桥驱动程序连接数据库 基本步骤: ...o(2)通过DriverManager获取数据库连接 o(3)通过Connection对象获取Statement对象 o(4)使用Statement接口执行SQL语句 ...Class.forName("DriverName");
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2数据库 Class....
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //装载数据库驱动 Connection con=DriverManager.getConnection(dbURL,user,password); //得到连接 System.out.println(con.getCatalog()); //打印...
Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...
Java写了一个连接Access数据库... Class.forName("com.hxtt.sql.access.AccessDriver").newInstance(); url = "jdbc:Access:///D:/dataAnalysis/accessDB.mdb"; connect = DriverManager.getConnection(url, "", "");