关于Java的jdbc中 DriverManager.registerDriver(driver); //注册驱动 有没有必要写的思考
加载数据库驱动的时候,有如下部分代码:
/1) 注册驱动程序
//给java.sql.Driver接口的引用赋值 com.mysql.jdbc.Driver 实现类对象
// Driver driver = new com.mysql.jdbc.Driver();
// DriverManager.registerDriver(driver); //注册驱动
先到数据库驱动包看下这个Driver类:
可以看到这个类里面有个static语句块,这里先来复习以下,什么时候会加载static语句块,有如下情况:
当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:
当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)
当调用某个类的静态方法时
当使用某个类或接口的静态字段时
当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时
当初始化某个子类时
当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类)
Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中:clinit。
特别要注意的是:使用final修饰的静态字段,在调用的时候不会对类进行初始化!以及类被加载了不一定就会执行静态代码块,只有一个类被主动使用的时候,静态代码才会被执行!
那么回到原来的问题,在创建Driver这个对象的时候:
Driver driver = new com.mysql.jdbc.Driver();
必然会执行其内的static语句块的,其static语句块的作用就和:
DriverManager.registerDriver(driver);
这段代码的作用是一样的,所以有必要再写一次这行代码吗?
我试着删除了这行代码,发现还是能顺利连接到数据库。
我写了一段代码计算一下driver的数量,如下所示:
public class jbdctest01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1) 注册驱动程序
//给java.sql.Driver接口的引用赋值 com.mysql.jdbc.Driver 实现类对象
// Driver driver = new com.mysql.jdbc.Driver();
// DriverManager.registerDriver(driver); //注册驱动
//注册驱动也可以使用Class.forName()创建Class对象时,会执行类的静态代码块, 在com.mysql.jdbc.Driver类的静态代码块中,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2)在当前程序与 数据库服务器建立连接
// Connection connection = DriverManager.getConnection("jdbc:mysql://数据库服务器IP地址:MySQL服务的端口号/数据库名", "登录服务器的用户名", "登录密码");
Enumeration<Driver> drivers = DriverManager.getDrivers();
int nums = 0;
//使用while循环来遍历驱动的个数
while(drivers.hasMoreElements()) {
nums ++;
//打印出驱动
System.out.println(drivers.nextElement());
}
//打印出驱动个数
System.out.println("驱动个数:" + nums);
}
}
测试结果如图所示:

用反射的方法加载驱动,驱动数为一个,这是意料之中的事情,在创建Driver这个对象时,会执行static中的代码块,因此会加载驱动,且数量为1
接下来测试,另外一种方法,代码如下:
public class jbdctest01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1) 注册驱动程序
//给java.sql.Driver接口的引用赋值 com.mysql.jdbc.Driver 实现类对象
Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver); //注册驱动
//注册驱动也可以使用Class.forName()创建Class对象时,会执行类的静态代码块, 在com.mysql.jdbc.Driver类的静态代码块中,注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2)在当前程序与 数据库服务器建立连接
// Connection connection = DriverManager.getConnection("jdbc:mysql://数据库服务器IP地址:MySQL服务的端口号/数据库名", "登录服务器的用户名", "登录密码");
Enumeration<Driver> drivers = DriverManager.getDrivers();
int nums = 0;
//使用while循环来遍历驱动的个数
while(drivers.hasMoreElements()) {
nums ++;
//打印出驱动
System.out.println(drivers.nextElement());
}
//打印出驱动个数
System.out.println("驱动个数:" + nums);
}
}
测试结果如图所示:

可以看到结果是2
接下来注释掉:DriverManager.registerDriver(driver); 这行代码,可以看到输出结果:

可以看到驱动个数为1个,说明了DriverManager.registerDriver(driver);这行代码可以去掉,如果加上,就会出现了两个驱动,因为在创建Driver这个对象的时候,其内的static语句块会自动执行了。
至此得出结论了。
另外还有一个小的疑问,就是一个对象执行的时候,是先创建类还是先执行其内的静态方法呢?我特意写了一个程序试了一下:
public class Teststatic {
public Teststatic(){
System.out.println("看看谁先被执行");
}
static {
System.out.println("我被执行了,哈哈哈");
}
}
class T {
public static void main(String[] args) {
Teststatic a = new Teststatic();
}
}
运行结果如下:

说明static语句块比构造方法执行的要早,我记得也是这样的。那么,我就有了一个疑问,因为Driver中的static,要用到Driver的实现类,如果先执行static语句块的话,不会抛出异常吗?因为这个时候Driver的实现类还没创建好啊
这里我犯了一个错误,就是误认为构造方法执行完毕之后类才被创建,其实不是的,是类创建好之后才会执行构造方法,所以是不会报错的。
关于Java的jdbc中 DriverManager.registerDriver(driver); //注册驱动 有没有必要写的思考的更多相关文章
- java链接JDBC中的?问题
String sql = "select * from student where name= ?"; PreparedStatement pst = conn.prepareSt ...
- java基础-jdbc——三种方式加载驱动建立连接
String url = "jdbc:mysql://localhost:3306/student?Unicode=true&characterEncoding=utf-8" ...
- Java的JDBC操作
Java的JDBC操作 [TOC] 1.JDBC入门 1.1.什么是JDBC JDBC从物理结构上来说就是java语言访问数据库的一套接口集合,本质上是java语言根数据库之间的协议.JDBC提供一组 ...
- jdbc中的Statement对象和Preparedstatement对象的区别,以及通过jdbc操作调用存储过程
一. java.sql.* 和 javax.sql.*的包的类结构 |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, p ...
- Java通过JDBC 进行MySQL数据库操作
转自: http://blog.csdn.net/tobetheender/article/details/52772157 Java通过JDBC 进行MySQL数据库操作 原创 2016年10月10 ...
- JDBC中常用的接口
JDBC常用的接口DriverManager 驱动管理器获得数据库链接 Connection 数据库链接接口 Statement 语句接口,用来静态操作SQL语句 PreparedStatement ...
- JDBC注册驱动的三种方式
JDBC注册驱动的三种方式 1.通过导入的JDBC的驱动包拿到的com.mysql.jdbc.Driver对象,利用java.sql.DriverManager对象的DriverManager.reg ...
- Oracle 在JDBC中使用 存储过程,包
前提: 在Oracle中已经定义 存储过程 和 存储函数 和 包 导入了Oracle的JDBC jar 包 package demo; import java.sql.Connect ...
- ava基础MySQL存储过程 Java基础 JDBC连接MySQL数据库
1.MySQL存储过程 1.1.什么是存储过程 带有逻辑的sql语句:带有流程控制语句(if while)等等 的sql语句 1.2.存储过程的特点 1)执行效率非常快,存储过程是数据库的服 ...
随机推荐
- 2019-ICLR-DARTS: Differentiable Architecture Search-论文阅读
DARTS 2019-ICLR-DARTS Differentiable Architecture Search Hanxiao Liu.Karen Simonyan.Yiming Yang GitH ...
- Beta冲刺 —— 5.31
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.讨论并解决每个人存在的问 ...
- Chisel3 - util - Mux
https://mp.weixin.qq.com/s/TK1mHqvDpG9fbLJyNxJp-Q Mux相关电路生成器. 参考链接: https://github.com/freechips ...
- Java并发编程 (二) 并发基础
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.CPU多级缓存-缓存一致性 1.CPU多级缓存 上图展示的是CPU高级缓存的配置,数据的读取和存 ...
- 数据库之 MySQL --- 数据处理 之 单行函数、组函数 (四)
[1] LOWER : 将字符串中的内容全部转成小写 UPPER : 将字符串中的内容全部转成大写 SELECT LOWER ('abAcD') FROM DUAL SE ...
- (Java实现) 洛谷 P1051 谁拿了最多奖学金
题目描述 某校的惯例是在每学期的期末考试之后发放奖学金.发放的奖学金共有五种,获取的条件各自不同: 院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上 ...
- Java 第十一届 蓝桥杯 省模拟赛 字母重新排列
字母重新排列 题目 问题描述 将LANQIAO中的字母重新排列,可以得到不同的单词,如LANQIAO.AAILNOQ等,注意这7个字母都要被用上,单词不一定有具体的英文意义. 请问,总共能排列如多少个 ...
- Java实现 LeetCode 257 二叉树的所有路径
257. 二叉树的所有路径 给定一个二叉树,返回所有从根节点到叶子节点的路径. 说明: 叶子节点是指没有子节点的节点. 示例: 输入: 1 / \ 2 3 \ 5 输出: ["1->2 ...
- Java实现 LeetCode 162 寻找峰值
162. 寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返 ...
- Java实现 蓝桥杯 历届试题 约数倍数选卡片
问题描述 闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数.例如,某次福尔摩斯拿走的卡片上写着数字" ...