加载数据库驱动的时候,有如下部分代码:

/1) 注册驱动程序
//给java.sql.Driver接口的引用赋值 com.mysql.jdbc.Driver 实现类对象
// Driver driver = new com.mysql.jdbc.Driver();
// DriverManager.registerDriver(driver); //注册驱动
先到数据库驱动包看下这个Driver类:

可以看到这个类里面有个static语句块,这里先来复习以下,什么时候会加载static语句块,有如下情况:

当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:

  1. 当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)

  2. 当调用某个类的静态方法时

  3. 当使用某个类或接口的静态字段时

  4. 当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时

  5. 当初始化某个子类时

  6. 当虚拟机启动某个被标明为启动类的类(即包含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); //注册驱动 有没有必要写的思考的更多相关文章

  1. java链接JDBC中的?问题

    String sql = "select * from student where name= ?"; PreparedStatement pst = conn.prepareSt ...

  2. java基础-jdbc——三种方式加载驱动建立连接

    String url = "jdbc:mysql://localhost:3306/student?Unicode=true&characterEncoding=utf-8" ...

  3. Java的JDBC操作

    Java的JDBC操作 [TOC] 1.JDBC入门 1.1.什么是JDBC JDBC从物理结构上来说就是java语言访问数据库的一套接口集合,本质上是java语言根数据库之间的协议.JDBC提供一组 ...

  4. jdbc中的Statement对象和Preparedstatement对象的区别,以及通过jdbc操作调用存储过程

    一. java.sql.*   和  javax.sql.*的包的类结构 |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, p ...

  5. Java通过JDBC 进行MySQL数据库操作

    转自: http://blog.csdn.net/tobetheender/article/details/52772157 Java通过JDBC 进行MySQL数据库操作 原创 2016年10月10 ...

  6. JDBC中常用的接口

    JDBC常用的接口DriverManager 驱动管理器获得数据库链接 Connection 数据库链接接口 Statement 语句接口,用来静态操作SQL语句 PreparedStatement ...

  7. JDBC注册驱动的三种方式

    JDBC注册驱动的三种方式 1.通过导入的JDBC的驱动包拿到的com.mysql.jdbc.Driver对象,利用java.sql.DriverManager对象的DriverManager.reg ...

  8. Oracle 在JDBC中使用 存储过程,包

      前提: 在Oracle中已经定义  存储过程  和  存储函数 和  包 导入了Oracle的JDBC   jar  包 package demo; import java.sql.Connect ...

  9. ava基础MySQL存储过程 Java基础 JDBC连接MySQL数据库

    1.MySQL存储过程   1.1.什么是存储过程 带有逻辑的sql语句:带有流程控制语句(if  while)等等 的sql语句   1.2.存储过程的特点 1)执行效率非常快,存储过程是数据库的服 ...

随机推荐

  1. MySQL8离线安装

    现在离线安装包: 登录官网准备下载 https://dev.mysql.com/downloads/mysql/ 2,开始下载 解压安装包: 开始解压: 解压完成: 新建init文件: 在解压目录下创 ...

  2. 一文带你深入理解JVM,看完之后你还敢说你懂JVM吗?颠覆you认知

    前言 今天带大家深入理解JVM,从入门到精通,希望大家能够喜欢~~~ 概念 JVM是可运行 Java 代码的假想计算机 ,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收,堆 和 一个存储方法域 ...

  3. 【Tomcat】JSP使用Session、Cookie实现购物车

    购物界面shop.jsp 初始页面 添加商品后,在session中设置属性,重定向回到shop.jsp,然后根据session的内容显示结果 Cookie设置setMaxAge可以延长session的 ...

  4. Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)

    试题 算法训练 Rotatable Number 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 Bike是个十分喜欢数学的聪明孩子.他发明了"可旋转数",其灵感 ...

  5. Java实现 LeetCode 695 岛屿的最大面积(DFS)

    695. 岛屿的最大面积 给定一个包含了一些 0 和 1 的非空二维数组 grid . 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相 ...

  6. (Java实现)蓝桥杯Excel地址

    历届试题 Excel地址 原题地址 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 Excel单元格的地址表示很有趣,它使用字母来表示列号. 比如, A表示第1列, B表示第2列, ...

  7. Java实现 LeetCode 560 和为K的子数组(某著名排序大法改编)

    560. 和为K的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] ...

  8. Java实现 LeetCode 413 等差数列划分

    413. 等差数列划分 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, - ...

  9. Java实现 LeetCode 239 滑动窗口最大值

    239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...

  10. Python快速入门文档

    前言 此文本质为本人学习Python过程中的笔记,部分地方叙述表达可能不够清晰,欢迎留言. (本文适合有一定程序语言基础的读者阅读(最好是c语言)) 一.基本语法 1.框架: (1)以缩进表示层次所属 ...