引言

如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据Class.forName("com.mysql.jdbc.Driver");

    public static Connection getConnection() throws ClassNotFoundException, SQLException {
if(connection == null){
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}
return connection;
}

之前没有想过为什么需要有这么一个语句,都是按照文档直接这么做的,在这篇文章中我来试着解释这么做的原因。

类加载机制

在这之前我们先来说下Java中的类加载机制。

在Java中如果想要使用一个类,则必须要求该类已经被加载到Jvm中,加载的过程实际上就是通过类的全限定名来获取定义该类二进制字节流,然后将这个字节流所表示的静态存储结构转换为方法去的动态运行时数据结构。同时在在内存中实例化一个java.lang.Class对象,作为方法区中该类的数据访问入口(供我们使用)。

而会触发类加载的会有如下几种情况(引用自<<深入理解Java虚拟机>>):

  1. 遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
  2. 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。

Class.forName

在Java官方文档中对Class.forName的解释为在运行时动态的加载一个类,返回值为生成的Class对象。

那么很明显在jdbc中使用Class.forName("com.mysql.jdbc.Driver");仅仅就是将com.mysql.jdbc.Driver类加载到Jvm中了,这个原因大多数人应该都知道。

但是我们要知道Class.forName貌似只是对类进行了加载,我们甚至都没有对返回的Class对象做任何操作,那么我们为什么后面就可以直接用了呢?

首先看Class.forName调用了native方法forName0(...);

@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
} private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller);

要注意forName0中有一个关键的参数boolean initialize,;该参数用来标识在将该类加载后是否进行初始化操作。可以看到代码中是true,就表示会进行初始化操作。

初始化过程实际上就是对变量赋值(不是赋初值,不会调用构造函数)的过程。包含所有类变量的赋值以及静态代码语句块的执行代码,包括对父类的初始化。

再看com.mysql.jdbc.Driver驱动类:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
} static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

该类中定义了一个静态代码块,静态代码快中创建了一个驱动类实例注册给了DriverManager,而静态代码块的内容会在初始化的过程中执行,所以才能通过DriverManager.getConnection直接获取一个连接。

其他加载类方法

我们需要明白的是在Java中并不是只有通过Class.forName()才能显示的加载类。那么为什么不使用其他的加载方法而偏偏选择Class.forName()呢?

ClassLoader.getSystemClassLoader().loadClass()

通过类加载器也可以将一个类加载到Jvm中。通过ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");也可以加载驱动类。

但是如果我们深入看下loadClass的实现:

public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
} protected Class<?> loadClass(String name, boolean resolve);

可以看到其调用了一个重载的方法,该方法也有一个boolean类型的变量boolean resolve,调用时默认为false。该参数用于标识是否对加载后的类进行链接操作,如果不进行连接操作则不会有初始化的操作。

所以如果使用这种加载类方式的话理论上来说是没发使用该驱动类的。

new关键字

也可以使用new关键字进行加载操作,在使用new关键字时会查看该类是否已经被加载,如果没有被加载的话则会进行加载操作。所以我们的类中也可以这样写:

public static Connection getConnection() throws ClassNotFoundException, SQLException {
if(connection == null){
new Driver();//会自动调用静态代码块
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
}
return connection;
}

但是实际上因为在驱动类的静态代码快中实际上已经有了实例化对象并注册到DriverMananger中的操作。所以这里根本就没有在实例化一个对象的过程。使用Class.forName即可,这也算是一个优化的过程吧。

可以不使用Class.forName("com.mysql.jdbc.Driver")

在测试的过程中发现即使不显示的使用Class.forName("com.mysql.jdbc.Driver")也能够连接到数据库,一时间觉得很奇怪。

深入跟踪代码后发现实际上只要我们引入了mysql的驱动包,那么在使用时会根据驱动包下提供的配置文件默认的创建一个类。

所以实际上只要引入了该驱动包,那么使用jdbc是可以直接通过DriverManage来获取连接。

public static Connection getConnection() SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}

为什么使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")的更多相关文章

  1. JDBC操作数据库,第一:jsp插入mysql数据库,坎坷摸索分享

    JSP连接数据库,坎坷摸索了好久,现在终于做好了,分享一下,希望对更多热爱编程学习的人有所帮助!!!谢谢 第一:首先准备的就是已经安装好Mysql,这里不做多叙述,百度可以做到. 然后在mysql数据 ...

  2. jdbc操作数据库(详细)

    JDBC是由java编程语言编写的类及接口组成,同时它为程序开发人员提供了一组用于实现对数据库访问的JDBC API,并支持SQL语言.利用JDBC可以将JAVA代码连接到oracle.DB2.SQL ...

  3. java数据库编程:JDBC操作及数据库

    掌握JDBC操作步骤, 掌握数据库驱动程序配置 可以使用JDBC进行数据库连接. JDBC本身是一个标准,因此操作步骤是固定的,以后只需要修改很少代码就可以达到不同数据库间连接转换功能. 操作步骤: ...

  4. jdbc 操作步骤详解

    package com.itheima.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql ...

  5. java数据库 JDBC操作MySQL数据库常用API 部门表和员工表 创建表 添加数据 查询数据

    package com.swift.department; import java.sql.Connection; import java.sql.PreparedStatement; import ...

  6. jdbc mysql crud dao模型 sql注入漏洞 jdbc 操作大文件

    day17总结 今日内容 l JDBC 1.1 上次课内容总结 SQL语句: 1.外键约束:foreign key * 维护多个表关系! * 用来保证数据完整性! 2.三种关系: * 一对多: * 一 ...

  7. JavaWeb用Jdbc操作MySql数据库(一)

    一.添加开发包.在JavaWeb中用jdbc操作数据库,使用方法与java一样,但是在处理开发包的问题上有点差别.JavaWeb不能将mysql-connector-java-5.1.7-bin.ja ...

  8. Java使用Jdbc操作MySql数据库(一)

    这个示例是Java操作MySql的基本方法. 在这个示例之前,要安装好MySql,并且配置好账户密码,创建一个logininfo数据库,在数据库中创建userinfo数据表.并且在表中添加示例数据. ...

  9. MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

随机推荐

  1. PMP测试实践- 内附PMBOK中字与备考资料

    最近笔者考了PMP(Project Management Professional )项目管理专业人士认证考试,主要为了系统学习下项目管理的整个过程与方法,结合PMP的理论与工作实践去更好的完成项目工 ...

  2. Analisis of Hello2 source

    GreetingServlet.java @WebServlet("/greeting") //为servelt指定URL pattern为:/greeting public cl ...

  3. github错误:fatal: remote origin already exists.

    原文链接:http://blog.csdn.net/dengjianqiang2011/article/details/9260435 如果输入$ Git remote add origin git@ ...

  4. JAVA_AesCBC纯净例子

    import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException ...

  5. 用Java写hello world

    public class HelloWorld{ public static void main(String[] args){ System.out.println("hello worl ...

  6. 反编译python打包的exe文件

    目录 1.前言 2.使用环境 3.还原过程 4.号外 5.exe文件和所用到的反编译工具 6.参考 7.去签名(补漏) 前言 拿到了利用驱动人生进行传播的病毒样本,发现是python打包成的exe文件 ...

  7. 为bootstrap+angularJs打造的表格代码生成器

    private void btnCreateCode_Click(object sender, EventArgs e) { string objName = txtObjName.Text; if ...

  8. RHEL7 配置网络yum源

    redhat系统安装好尽管默认带有yum,但是redhat的更新包只对注册用户有效(收费).所以需要更换yum源. 基本的流程就是: 1.删除redhat7.0系统自带的yum软件包: 2.自行下载所 ...

  9. 解决 Visual Studio 点击添加引用无反应的问题

    如遇到vs2010 点击添加引用无反应,主要是因为windows系统推送的更新问题,把windows系统推送的更新都更新一遍就好了. 如果已经安装VS后 Windows系统推荐的更新.360推荐的安全 ...

  10. gc笔记(转)

    GC,即就是Java垃圾回收机制.目前主流的JVM(HotSpot)采用的是分代收集算法.与C++不同的是,Java采用的是类似于树形结构的可达性分析法来判断对象是否还存在引用.即:从gcroot开始 ...