JDBC中运用Class.forName("xxx")的意义
JDBC中使用Class.forName(xxx)的意义Class.forName方法介绍在java.lang.Class中,有两个重载的forName方
JDBC中使用Class.forName("xxx")的意义
Class.forName方法介绍
在java.lang.Class中,有两个重载的forName方法,分别是:
static?Class<?>forName(String?className),该方法等价于Class.forName(className, true, this.getClass().getClassLoader())static?Class<?>forName(String?className, boolean?initialize,ClassLoader?loader),其中3个参数分别表示:className - 所需类的完全限定名,initialize - 是否必须初始化类,loader - 用于加载类的类加载器。
forName方法的作用就是:
使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的?Class?对象。给定一个类或接口的完全限定名,此方法会试图定位、加载和链接该类或接口。指定的类加载器用于加载该类或接口,如果参数loader?为 null,则该类通过引导类加载器加载。只有?initialize?参数为?true且以前未被初始化时,才初始化该类。
其他的都很容易懂,就是当第二个参数为true时,到底初始化的是什么呢?可以通过下面这个例子来了解:
?
[java]?view plaincopy
- package?wen.hui.test.forname;??
- ??
- /**?
- ?*?@author?whwang?
- ?*?
- ?*/??
- public?class?TestClassForName?{??
- ??
- ????public?static?void?main(String[]?args)?throws?ClassNotFoundException?{??
- ????????(new?TestClassForName()).loadClass();??
- ????}??
- ??????
- ????@SuppressWarnings("unchecked")??
- ????public?Class<Test>?loadClass()?throws?ClassNotFoundException?{??
- //??????Class<Test>?clazz?=?(Class<Test>)?Class.forName("wen.hui.test.forname.Test");??
- ????????Class<Test>?clazz?=?(Class<Test>)?Class.forName("wen.hui.test.forname.Test",?true,?getClass().getClassLoader());??
- ????????return?clazz;??
- ????}??
- ??????
- }??
- ??
- class?Test?{??
- ??????
- ????static?{??
- ????????System.err.println("类的静态初始化块");??
- ????}??
- ??????
- ????public?Test()?{??
- ????????System.err.println("实例化类");??
- ????}??
- ??????
- }??
运行后,打印:类的静态初始化块
没错,Class.forName的第二个参数为true时,就是要求JVM在加载类后,初始化类的静态字段和静态块。
?
JDBC中使用Class.forName("xxx")的意义
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过上面的介绍,已经了解了Class.forName()方法的作用就是为了动态加载类,并决定是否需要初始化类的静态部分,而在JDBC规范中明确要求Driver(数据库驱动)类必须向DriverManager注册自己。写到这里,相信大家都应该明白为什么在我们加载数据库驱动包的时候有的仅仅需要Class.forName(xxx);而有的需要Class.forName(xxx).newInstance()。
下面以MySQL为例子,来看看MySQL的com.mysql.jdbc.Driver类是怎么写的,MySQL的Driver类源码(5.x)
?
[java]?view plaincopy
- public?class?Driver?extends?NonRegisteringDriver?implements?java.sql.Driver?{??
- ????//?~?Static?fields/initializers??
- ????//?---------------------------------------------??
- ??
- ????//??
- ????//?Register?ourselves?with?the?DriverManager??
- ????//??
- ????static?{??
- ????????try?{??
- ????????????java.sql.DriverManager.registerDriver(new?Driver());??
- ????????}?catch?(SQLException?E)?{??
- ????????????throw?new?RuntimeException("Can't?register?driver!");??
- ????????}??
- ????}??
- ??
- ????//?~?Constructors??
- ????//?-----------------------??
- ??
- ????/**?
- ?????*?Construct?a?new?driver?and?register?it?with?DriverManager?
- ?????*??
- ?????*?@throws?SQLException?
- ?????*?????????????if?a?database?error?occurs.?
- ?????*/??
- ????public?Driver()?throws?SQLException?{??
- ????????//?Required?for?Class.forName().newInstance()??
- ????}??
- }??
在使用JDBC连接MySQL数据库时,使用Class.forName("com.mysql.jdbc.Driver")就是为了向DriverManager注册自己;当然使用Class.forName("com.mysql.jdbc.Driver").newInstance()当然也没错,只是没有必要,因为后者还会生成Driver类的实例,而这个是我们没有用的,没有必要创建它。如果在Driver类中那个static块里面的部分写在了构造方法中,那么就必须使用Class.forName("com.mysql.jdbc.Driver").newInstance()来向DriverManager注册了。