Class.forName()如何工作?

我刚刚了解了java.sql package 。 它使用Class.forName()来dynamic加载扩展DriverManager的驱动程序。 然后我们使用DriverManager.getConnection()方法获得连接。

那么整个事情是如何工作的呢?
如何DriverManager类知道如何获得连接,而不使用实际的驱动程序的类名称。

我们也可以使用Class.forName()为自定义应用程序…如果这是解释一个例子,我会很高兴。

Class.forName只是加载一个类,包括运行它的静态初始值设定项,如下所示:

 class Foo { static { System.out.println("Foo initializing"); } } public class Test { public static void main(String [] args) throws Exception { Class.forName("Foo"); } } 

您所谈论的所有其他程序都是针对JDBC的。 驱动程序 – 实现Driver ,它不扩展DriverManager – 只需使用DriverManager.registerDriver注册适当的实例。 然后,当DriverManager需要为特定连接string查找驱动程序时,它会acceptsURL调用每个已注册的驱动程序的acceptsURL ,直到有人说“是的,我可以作为该连接的驱动程序”。

请注意,这种注册驱动程序的方式是相当老式的 – 查看DriverManager的文档以获取更多的数据源的现代方法。

Class.forName(..)加载并初始化目标类。 这又意味着调用静态初始化块(在static { .. }定义的代码。

例如,如果您查看MySQL的驱动程序,那么在该静态块中,驱动程序正在注册自己: DriverManager.registerDriver(new Driver());

你可以省略Class.forName(..)并注册驱动程序,如果你能“负担”MySQL驱动程序的编译时间依赖。

也就是说,使用Class.forName(..)来初始化应用程序中的类是很less有用的,因为编译时间依赖并不是一个问题。

另请注意,从版本4开始,JDBC 不再需要 Class.forName(..)通过使用服务提供者机制,您可以指示驱动程序pipe理器通过系统属性加载什么内容。

当我们使用new操作符创build一个类的实例时,它会做两件事

  1. 将类加载到内存中(如果未加载) – 这意味着从.class文件创build类的内存中表示,以便可以创build实例。 这包括初始化静态variables(解决该类)
  2. 创build该类的一个实例并存储对该variables的引用。

Class.forName只做第一件事。 它将类加载到内存中,并将该引用作为Class的实例返回。 如果我们想创build一个实例,那么我们可以调用该类的newInstance方法。 这将调用默认的构造函数(无参数构造函数)。 请注意,如果默认构造函数不可访问,则newInstance方法将抛出IllegalAccessException 。 如果这个类是一个抽象类或接口,或者它没有默认的构造函数,那么它将抛出一个InstantiationException 。 如果在parsing该类时出现ExceptionInInitializerError ,则会抛出ExceptionInInitializerError

如果默认构造函数没有定义,那么我们必须使用reflectionAPI来调用defiend构造函数。

但是Class.forName的主要优点是,它可以接受类名作为String参数。 所以我们可以dynamic地传递类名。 但是,如果我们使用new运算符创build类的实例,则不能dynamic更改类名称。

Class.forName() inturn将调用调用方ClassLoader的loadClass方法(调用Class.forName的类的ClassLoder)。

默认情况下, Class.forName()parsing该类。 这意味着,初始化该类中的所有静态variables。 同样可以使用Class.forName(String name,boolean initialize,ClassLoader loader)的重载方法进行更改

使用Class.forName()加载jdbc驱动程序的主要原因是,驱动程序可以dynamic更改。 在静态块中,所有的驱动程序将创build一个自己的实例,并使用DriverManager.registerDriver()方法向DriverManager注册该类。 由于Class.forName(String className)默认parsing类,它将初始化静态初始化器。 所以当我们调用Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver") ,Driver类将被加载,实例化并注册到DriverManager

所以如果你使用新的Operator,你必须做以下的事情。
码:

 Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver(); DriverManager.registerDriver(drv); 

在SQL示例中经常提到Class.forName()的原因是因为没有什么神奇的东西来告诉JDBC DriverManager 如何映射提供给真实驱动程序的JDBC URL。

例如“mysql”应该映射到给定的MySQL类,“thin”映射到Oracle类,“as400”映射到DB2 / 400类。

通过显式加载类,这允许运行在DriverManager中注册自己的类中的代码。

这些日子里存在的魔术挂钩允许JVM自动发现驱动程序(如果足够新的话),这样的调用是多余的,但出于习惯,许多人仍然使用它。