首先来看看我们初学jdbc连接数据库时的demo:
//注册mysql驱动
Class.forName("com.mysql.jdbc.Driver");
//建立数据库对象
Connection conn = DriverManager.getConnection(url, user, password);
//建立操作对象
Statement stmt= conn.createStatement();
//结果集
ResultSet rs = stmt.executeQuery("select * from test");
其中的Class.forName(driver)
被我们叫做注册mysql的驱动。
问题来了,为什么这句话就是注册驱动了? 为了理解这个问题,我们需要了解一下:
- Class.forName的作用是什么?
- 了解com.mysql.jdbc.Driver类
了解Class.forName()
从文档上我们知道,
Class.forName
通过一个类的全限定名可以加载并初始化类。
继续,我们需要了解类的加载过程。
类的加载过程包括:加载-验证-准备-解析-初始化。
《深入理解Java虚拟机 2》中第七章 虚拟机加载机制 中介绍到有且只有5种情况必须对类进行“初始化”,称为主动引用。除此之外,都不会触发初始化,称为被动引用。
详细的内容后面会介绍,看了书就知道,Class.forName()
属于主动引用的场景,所以会触发类的初始化。
那么,类的初始化做了什么?
ps:有一点要注意,类的初始化并不是Test test = new Test();
。new Test()执行了实例构造器<init>()方法,类的实例化是执行了类的构造器<clinit>()方法。
从定义上看:<clinit>() 方法是由编译器自动收集所有类变量的赋值动作和静态语句块(static{})中的语句合并产生的。
所以类的初始化会执行static变量以及static{}中的语句,初始化子类前必须先初始化父类。
看个实例:
public class ClassForNameExp1 {
//静态代码块
static {
System.out.println("执行了静态代码块");
}
//静态变量
private static String staticFiled = staticMethod();
//赋值静态变量的静态方法
public static String staticMethod(){
System.out.println("执行了静态方法");
return "给静态字段赋值了";
}
public ClassForNameExp1(){
System.out.println("执行了构造函数");
}
}
public class ClassForName {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("reflect.ClassForNameExp1");
}
}
>执行结果:
执行了静态代码块
执行了静态方法
可以看出来只执行了静态变量和静态代码块。
了解com.mysql.jdbc.Driver类
看源代码:
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
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!");
}
}
}
public class DriverManager {
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}
public static synchronized void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
}
Dirver类的static{}方法的作用 是将自己实例化后添加进DriverManager的注册驱动队列里。
真相大白了。
附:类的主动引用及被动引用
暂未编写,阅读《深入理解Java虚拟机 2》中第七章-虚拟机加载机制章节。