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

  获取一个数据库连接的通用模板如下:
     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会自动去加载合适的驱动。

为什么要使用class.forname在DriverManager.getConnection之前的更多相关文章

  1. OAF_JDBC系列2 - 通过JDBC连接SQLSERVER数据库DriverManager.getConnection

    d try{          Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");          St ...

  2. Eclipse中利用JSP把mysql-connector-java-8.0.13.jar放到WebContent\WEB-INF\lib中连接MySQL数据库时Connection conn = DriverManager.getConnection(url,username,password)报错的解决办法

    开发环境: 1.系统:windows 7/8/10均可 2.jdk:1.8.0_144 3.服务器:apache-tomcat-9.0.8 4.IDE:eclipse+jsp 0.网页代码如下: &l ...

  3. JDBC中的DriverManager.getConnection(url)中的参数url

    1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...

  4. jdbc的数据库驱动类DriverManager.getConnection()详解

    1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...

  5. Connection conn = DriverManager.getConnection("jdbc:odbc:bbs");

    Connection conn = DriverManager.getConnection("jdbc:odbc:bbs"); 这是JDBC连接数据库的时候用的一句话,,Conne ...

  6. JDBC详解系列(三)之建立连接(DriverManager.getConnection)

      在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码 ...

  7. SparkCore | Rdd| 广播变量和累加器

    Spark中三大数据结构:RDD:  广播变量: 分布式只读共享变量: 累加器:分布式只写共享变量: 线程和进程之间 1.RDD中的函数传递 自己定义一些RDD的操作,那么此时需要主要的是,初始化工作 ...

  8. Spring Data 起步

    [Maven 坐标]G A V ……………………………………………………………………………………………………………………………………………… [JDBC] Connection 连接数据库 State ...

  9. 【大数据】SparkCore学习笔记

    第1章 RDD概述 1.1 什么是RDD RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象.代码中是一个抽象类,它代表一个不可变.可 ...

随机推荐

  1. 一起学HTML基础-CSS样式表常用样式属性

    样式属性 背景与前景: background-color:#F90; /*背景颜色,样式表优先级最高*/ background-image:url(路径); /*设置背景图片(默认)*/ backgr ...

  2. skiing

    package noj_skiing; import java.util.*; import java.math.*; public class Main { public static void m ...

  3. BZOJ 1109: [POI2007]堆积木Klo

    1109: [POI2007]堆积木Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 948  Solved: 341[Submit][Statu ...

  4. 关于使用struts2时子窗体页面跳转后在父窗体打开的问题以及Session过期后的页面跳转问题

    问题1:传统的系统界面,iframe了三个页面,上,左,右,用户点击注销的按钮在上面得top.jsp里面,方法:<a href="../adminAction/admin_logout ...

  5. text-indent无效解决方案

    text-indent是用来字符缩进的. 1.text-indent所在的元素是行内元素而非块级元素.比如用在span,a等行内元素上.解决方案:在行内元素加上display:block; 或者把目标 ...

  6. SVN分支研究

    在结合之前总结的定制开发的产品版本开发问题解决的方法:http://www.cnblogs.com/EasonJim/p/5971906.html,今天来研究以下用SVN处理这类的问题. 研究SVN分 ...

  7. vs2010 mvc3安装时报错

    今天在研究以往的商城项目时,由于前台使用的是MVC3,在没有安装MVC3的插件时,提示未能加载项目,但是在安装过程中,又提示安装失败: 决定折腾一下->居然找到一篇以前别人写的神作,特此记录一下 ...

  8. hdu 4403 dfs

    巨麻烦的模拟题orz.... 先确定等号的位置,然后两层dfs,分别算等号前面的和后面的,再比较 话说这题竟然不开long long都能水过 #include <iostream> #in ...

  9. Unity3d5.0 新UI之2048

    因为汽车系统没写出来所以,纠结之中,弄了弄新版本的UI. 做了个2048. 新版本的unity的UI必须以Canvas为基底来呈现,如果没有加画布的话可是显示不出来东西的哦. 而且作为UI上的所有组件 ...

  10. 获取URL列表,设置代理请求URL,https的加密方式处理

    做了一个测试的一个小工具,需求如下: 1.有一批URL列表,需要知道哪个URL请求响应内容中包含http:关键字的. 2.url请求包括http和https 2种协议 3.要部署在linux服务器上, ...