Aaron Johnson对Class.forName()的解释_翻译

本文深入探讨了Java中Class.forName()方法的工作原理及其在数据库驱动加载中的作用,解释了类的定位、加载、链接和初始化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A reader asked a question via a comment a couple months ago that I didn't really have an answer for (and had always kind of wondered the same thing). In the original post (which showed how to use JDBC with ColdFusion), I used the following snippet of code:
几个月之前,一个读者通过一篇评论向我提了一个问题,我一直没有真正给出答案(我一直在考虑一件事情)。我在原来的职位(我负责展示如何在ColdFusion上使用JDBC)时,我曾使用下面的代码片断:


Class.forName("jdbc.DriverXYZ");
Connection con = DriverManager.getConnection(url,
"myLogin", "myPassword");

and the reader wanted to know what the
Class.forName(..) method did. The most common answer you'll hear is that it loads the database driver, which, while technically true, is shallow. Where does it get loaded? How does it happen? And why?

那位读者想知道Class.forName(..) 方法到底做了些什么。通常你所听到的大多数回答都是它是用来加载数据库驱动的,虽然这个答案在技术上来说是正确的,但是太浅显了。到底是在哪里加载的?是怎么工作的?还有为什么要这样用?

To answer the question I started with the JavaDoc for the Class.forName() method. According to the documentation, the method:
... attempts to locate, load, and link the class or interface.I wasn't perfectly clear on what "locate, load, and link" meant, so I did a little digging through the
Java Language Specification. According to chapter 12 of the JLS: Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.Next, again according to the JLS, it must be transformed from it's binary representation to something the Java virtual machine can use, this process is called linking. Finally, the class is initialized, which is the process that executes the static initializer and the initializers for static fields declared in the class.

要回答这个问题,我从Java文档中关于Class.forName()方法说明开始。根据文档的说明:…试图定位,加载,连接类或者接口。我不是很清楚到底“定位,加载和连接”是什么意思,因此我小小的研究了一下《Java 语言说明书》。根据其第12章关于JLS的说明:加载是指-根据指定的类或者接口的名字,找到其实际二进制文件的处理过程,或许是很匆忙的处理,但更典型的是指检索之前被编译器编译过的二进制文件,并且构造,二进制文件就是.class文件,它可能是类或接口。接着,还是依据JLS,二进制文件将被转化为Java虚拟机可以使用的东西,这个操作称为“连接”。最后类被初始化,如执行其静态初始化程序与初始化类中声明的静态变量。


So then back to the original problem, when Class.forName() is called with an argument like this:
所以我们现在回到最开始的问题,当Class.forName()被调用时,会有参数传入就像这样:

Class.forName("org.gjt.mm.mysql.Driver");

the classloader attempts to load and link the
Driver class in the "org.gjt.mm.mysql" package and if successful, the static initializer is run. The MySQL Driver (download the source code) static initializer looks like this:
类加载器尝试去加载和连接"org.gjt.mm.mysql"包里的Driver类,如果成功了,静态初始化程序将被运行,

MySQL Driver类(在这里下载源代码)静态初始化程序是这样的:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}

So it calls a static method in the
java.sql.DriverManager class which apparently registers a copy of itself when it loads.

从上面的代码中可以看到,它调用了java.sql.DriverManager的静态方法,很显然在它被加载的时候,它注册了一个自己的实例。


So now I understand the where and the how, what about why? To understand the why you have to look at the next line in the initial code example:
因此到目前为止我明白了在哪里加载与如何加载的,但是为什么非要这么做呢?想要了解为什么,你需要看下面的初始化代码样例:


Connection con = DriverManager.getConnection(url,
"myLogin", "myPassword");

The
DriverManager class (view DriverManager source here) returns a database connection given a JDBC URL string, a username and a password. In order to create that connection, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it (ie: the registerDriver(Driver driver) method illustrated above) and calls the acceptsURL(url) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.
So there you have it. Class.forName explained.

DriverManager类在给予它一个JDBC URL字符串,一个用户名与密码后,它会返回一个数据库的连接对象,DriverManager类需要知道你要使用哪个数据库驱动程序。要做到这一点,它要遍历一个驱动数组(内部由一个Vector实现),那些驱动就是之前注册过的(例如:上文中的registerDriver(Driver driver)方法)并且逐个调用数组中驱动类的acceptsURL(url)方法,实际上是让驱动程序反馈其是否可以处理这个 JDBC URL连接字符串。直到现在你该明白Class.forName的作用了吧。^_^

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值