博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么要使用class.forname在DriverManager.getConnection之前
阅读量:5173 次
发布时间:2019-06-13

本文共 3347 字,大约阅读时间需要 11 分钟。

在getConnection之前为什么要调用Class.forName   获取一个数据库连接的通用模板如下:      String driver = "oracle..OracleDriver";   String url = ":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.");   }   }   class {
  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..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 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会自动去加载合适的驱动。

转载于:https://www.cnblogs.com/w-wfy/p/6180865.html

你可能感兴趣的文章
数据库
查看>>
常见Struts、Hibernate、Spring、J2EE、ibatis、Oracle等开发框架架构图及其简介
查看>>
Java为何大行其道
查看>>
CFileDialog的使用方法简单介绍
查看>>
send,recv,sendto,recvfrom
查看>>
C#开发问题汇总
查看>>
Kettle
查看>>
[复习]Python基础回顾
查看>>
LNMP
查看>>
java 读写锁
查看>>
_itoa_s替换 itoa
查看>>
Nginx负载均衡
查看>>
【bzoj3456】城市规划(多项式求逆+dp)
查看>>
#ifdef 支持Mac #ifndef 支持Windows #if defined (Q_OS_WIN) 应该可以再两个系统通用
查看>>
linux源码中的核心数据结构
查看>>
EF执行SQL语句
查看>>
Ogre学习教程:Ogre1.8.1+VS2010环境配置2(转)
查看>>
webpack 样式表抽离成专门的单独文件并且设置版本号
查看>>
个人作业week7——前端开发感想总结
查看>>
VC Dimension -衡量模型与样本的复杂度
查看>>