浅析使用JDBC操作MySQL需要添加forname (“com.mysql.jdbc.Driver")

  

  

如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据forname

        (“com.mysql.jdbc.Driver”);   公共静态连接getConnection()抛出ClassNotFoundException, SQLException {   如果(连接==null) {   forname (“com.mysql.jdbc.Driver”);   连接=DriverManager.getConnection (" jdbc: mysql://localhost: 3306/xxx # 63; serverTimezone=UTC”,“根”,“xxxxxx”);   }   返回连接;   } 之前      

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

  

  

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

  

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

  

而会触发类加载的会有如下几种情况(引用自& lt; & lt;深入理解Java虚拟机在祝辞):
  

  

1。遇到新的、getstatic putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用新关键字实例化对象的时候,读取或设置一个类的静态字段(被最终修饰,已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
  

  

2。使用. lang。反映包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  

  

3。当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  

  

4。当虚拟机启动时,用户需要指定一个要执行的主类(包含主要()方法的那个类),虚拟机会先初始化这个主类。

  

  

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

  

那么很明显在jdbc中使用<代码> forname (“com.mysql.jdbc.Driver”);>   

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

  

首先看forname调用了本地方法forName0 (…),

        @CallerSensitive   公共静态Class<& # 63;比;forName(字符串名称)   抛出ClassNotFoundException {   Class<& # 63;比;调用者=Reflection.getCallerClass ();   返回forName0(类名,真的,ClassLoader.getClassLoader(调用者),调用者);   }      私有静态原生Class<& # 63;比;forName0(字符串名称、布尔值初始化类加载器加载程序,Class<& # 63;比;调用者);   之前      

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

  

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

  

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

        公共类驱动NonRegisteringDriver实现java.sql延伸。司机{   公共司机()抛出SQLException {   }      静态{   尝试{   DriverManager。registerDriver(新司机());   }捕捉(SQLException var1) {   把新RuntimeException(“不能登记司机!”);   }   }   } 之前      

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

  

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

  .loadClass

<代码> ClassLoader.getSystemClassLoader()()

  

通过类加载器也可以将一个类加载到Jvm中。通过<代码> ClassLoader.getSystemClassLoader () .loadClass (“com.mysql.jdbc.Driver”);>

浅析使用JDBC操作MySQL需要添加forname (“com.mysql.jdbc.Driver")