类的加载:Class.forName与ClassLoader.loadClass

 

Class.forNameClassLoader.loadClass方法都用来动态的加载一个类(都返回一个java.lang.Class对象),区别在于他们使用的ClassLoader和是否执行类的初始化。

1.1      Class.forName

这是一个类方法,该方法除了加载类到JVM中,还会执行类的初始化,即类的静态初始化。

 

使用Class.forName最常用的形式是Class.forName(String qualifiedClassName),如写JDBC程序常用到的加载某个数据库Driverjvm的代码:

Class.forName("com.mysql.jdbc.Driver");

该函数使用调用者的ClassLoader, 即调用该行代码的类所使用的ClassLoader,返回一个参数名所对应的Class对象。

另外还有一个带三个参数的forName方法, Class.forName(String, boolean, ClassLoader),参数分别用来指定类名,是否初始化和要使用的ClassLoader

1.2      ClassLoader.loadClass

这是一个实例方法,可以使用一个特定的ClassLoader来加载一个类。该方法不会执行类的初始化,只由当该类第一次被使用时才会执行类的初始化,比如调用该类的一个静态方法或创建该类的一个对象。

1.3      使用哪一个方法

1.3.1       ClassLoader

不同的ClassLoader加载类时会从不同的位置来查找类的.class文件,所以如果要加载的类不在默认的查找位置时,就应该指定要使用的ClassLoader,否则会得到java.lang.ClassNotFoundException的错误。为了灵活性,你应该总是提供一个来参数指定ClassLoader而不是使用默认的ClassLoader,即使用带三个参数的forNameloadClass方法。关于不同的ClassLoader如何查找及加载类请参考ClassLoder一文。

1.3.2       是否要执行类初始化

在上面加载Mysql Driver的例子中,我们本身并不需要创建MySqlDriver对象,只需要加载DriverJVM,并执行类的初始化(可能执行注册自己到Driver Manger的代码)。所以可以使用forName方法,如果使用ClassLoader.loadClass则需要像下面这样:

ClassLoader cl = …;

cl.loadClass("com.mysql.jdbc.Driver").newInstance(); //创建对象仅仅为了执行类初始化,对象本身并不会被使用。

 

如果已知类的初始化是一个比较耗时的过程,则可以将其初始化推迟到该类被一次使用时。另外执行类的初始化代码失败会抛出java.lang.ExceptionInInitializerError异常。此时加载的类就变得不可用。类的初始化错误往往很难跟踪,所以如果要在一个特定点捕获并处理该异常就可以使用Class.forName并放在一个try块中。但是不要试图重新加载该类,因为一个类只能被同一个ClassLoader加载一次。

 

1.4      参考:

[ldcs] http://www.javaworld.com/javaworld/javaqa/2003-03/01-qa-0314-forname.html?page=1. 2003.03

 

 

发布了40 篇原创文章 · 获赞 2 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章