9.6 Class.forName方法

熟悉Java EE开发的开发人员对于Class.forName方法应该并不陌生。在Java EE开发中,Class.forName方法的一个典型应用是加载使用JDBC操作数据库时的数据库驱动。比如,当需要加载Apache Derby数据库的嵌入式驱动时,可以使用代码Class.forName("org.apache.derby.jdbc.EmbeddedDriver")。不过这种做法从JDBC 4.0开始就不再需要了,因为java.sql.DriverManager类支持了使用服务发现机制来自动查找可用的数据库驱动。

Class. forName方法的作用是根据Java类的名称得到对应的Class类的对象。该方法有两种重载形式。第一种是使用3个参数的复杂形式。3个参数依次表示Java类的名称、是否初始化Java类,以及用于加载Java类的类加载器对象。如果第3个参数的值为null,则使用启动类加载器来进行加载。第二种是只使用一个参数的简单形式,相当于第一种重载形式中的第2个和第3个参数的值分别是true和this.getClass().getClassLoader()。

Class. forName方法与ClassLoader类的重要区别在于Class.forName方法可以初始化Java类,而ClassLoader类的对象是不行的。这也是Class.forName方法的优势所在。初始化Java类意味着Java类中的静态变量会被初始化,同时静态代码块也会被执行。代码清单9-13给出了一个简单的包含静态代码块的Java类。在该类被初始化时,会在控制台输出提示信息。

代码清单9-13 包含静态代码块的示例Java类


public class ClassForNameTest{

static{

System.out.println("初始化");

}

}


代码清单9-14展示了分别使用Class.forName方法和ClassLoader类来加载代码清单9-13中的ClassForNameTest类时的不同之处。在调用Class.forName方法时会输出与初始化类相关的提示信息,而调用ClassLoader类的loadClass方法则不会。

代码清单9-14 Class.forName方法与ClassLoader类在加载类时的不同之处


public void classForNameVsLoader()throws ClassNotFoundException{

String className="com.java7book.chapter9.ClassForNameTest";

Class<?>clazz1=Class.forName(className);

ClassLoader loader=this.getClass().getClassLoader();

Class<?>clazz2=loader.loadClass(className);

}


这也是为什么在JDBC 4.0之前需要使用Class.forName方法来加载数据库驱动的Java类的原因。在不支持驱动的自动发现之前,在数据库驱动类的静态代码块中可以添加必要的驱动注册和初始化的逻辑,在驱动的Java类被初始化时,完成相关的处理。