关于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)执行效率非常快,存储过程是数据库的服 ...
随机推荐
- raw_input和input
昨天在OJ上做CTF的题目,发现有道python的题目很有意思,让我知道了raw_input和input的区别,并且能干一些别的事情. 官方文档上说,input()相当于eval(raw_input( ...
- 高性能可扩展mysql 笔记(五)商品实体、订单实体、DB规划
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.商品模块 商品实体信息所存储的表包括: 品牌信息表: create table `brand_i ...
- Java实现 LeetCode 783 二叉搜索树节点最小距离(遍历)
783. 二叉搜索树节点最小距离 给定一个二叉搜索树的根节点 root,返回树中任意两节点的差的最小值. 示例: 输入: root = [4,2,6,1,3,null,null] 输出: 1 解释: ...
- Java实现 蓝桥杯 算法训练 纪念品分组
问题描述 元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作.为使得参加晚会的同学所获得的纪念品价值 相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价 ...
- Java中继承的详细用法
关于上一篇构造方法后的继承方法 构造方法链接 extends是继承的关键字 例: 下面的代码BB和CC就是AA的子类 允许一个父类有多个子类,但不允许一个子类有多个父类 /*final*/ class ...
- Java实现 洛谷 P2141 珠心算测验
import java.util.LinkedList; import java.util.Scanner; public class Main { private static Scanner ci ...
- 阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路
近日,阿里云杨敬宇在CSDN阿里云核心技术竞争力在线峰会上进行了<5G基础设施-阿里云边缘计算的技术演进之路>主题演讲,针对5G时代下,行业和技术的趋势.边缘计算产业通识以及阿里云边缘计算 ...
- Swagger使用的时候报错:Failed to load API definition
NuGet添加Swashbuckle.AspNetCore,在Startup.cs添加和启用中间件Swagger public void ConfigureServices(IServiceColle ...
- mysql基础-数据库表的管理-记录(四)
0x01 MySQL中字符大小写 1.SQL关键字及函数不区分大小写 2.数据库.表及视图名称的大小写区分与否取决于底层OS及FS 3.存储过程.存储函数及事件调度器的名字不区分大小写,但触发器区分大 ...
- 体验SpringBoot(2.3)应用制作Docker镜像(官方方案)
关于<SpringBoot-2.3容器化技术>系列 <SpringBoot-2.3容器化技术>系列,旨在和大家一起学习实践2.3版本带来的最新容器化技术,让咱们的Java应用更 ...