在Java开发特别是数据库的开发中,经常会用到Class.forName()方法。通过查询Java Documentation我们会发现Class.forName()方法的作用是动态加载类。在加载完成后,一般还要调用Class下的newInstance()静态方法来产生实例化对象以便进行操作。所以,如果只是用Class.forName()是没有用的,其最终的目的是为了产生实例化对象。
Class.forName()方法返回的是一个类,它通过要求JVM查找并加载指定的类,再通过newInstance()方法产生指定类的实例化对象。在初始化一个类,产生一个实例化对象时,newInstance()和new除了一个是方法,一个是关键字的区别外,最主要的区别在于:创建对象的方式不一样,前者使用类加载机制,而后者是创建了一个新类。其次,newInstance()的使用有局限,只能调用无参的构造函数,而new关键字没有这个限制。那么为什么会有两种创建对象的方式呢?主要考虑到软件的可扩展性、可重用性和可伸缩性。
Class.forName()返回的是一个类,而Class.forName().newInstance()返回的是一个Object,所以在调用后面的方法时,我们需要显式的去对类型进行转换成我们需要的类型。但是做过数据库开发的会发现,为什么有时候我们加载数据库驱动包的时候有的却没有调用newInstance()方法了?有的时候jdbc连接数据库的时候写的是Class.forName("xx xx xx"),而有一些写的是Class.forName("xx xx xx").newInstance(),为什么会有两种写法呢?
刚才提到,Class.forName()的作用是要求JVM查找并加载指定的类,如果类中有静态初始化器的话,JVM必然会执行该类的静态代码段。而在JDBC规范中明确提到,要求Driver这个类必须向DriverManager注册自己,代码如下:
public class MyJDBCDriver implements Driver{
static{
DriverManager.registerDriver(new MyJDBCDriver());
}
}
既然在静态初始化器中已经进行了注册,所以我们在使用JDBC的时候只需要Class.forName("xx xx xx")就可以了。
那么我们为什么要用newInstance()来创建对象呢?Java中的工厂模式可以给我们具体的答案。例如: class c = Class.forName("example");factory=(ExampleInterface)c.newInstance();
其中ExampleInterface是example的接口,可以写成如下形式:String className="example";class c = Class.forName(className);factory=(ExampleInterface)c.newInstance();
进一步可以写成如下形式:String className=readfromXMLConfig;//从xml配置文件中获取类名的字符串
class c = Class.forName(className);factory=(ExampleInterface)c.newInstance();
上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不用改变,甚至可以更换成Example类的兄弟类Example2,Example3.......只要它们继承ExampleInterface就可以了。
从JVM的角度看,我们使用new关键字创建一个对象时,这个类可以没有被加载。但是使用newInstance()方法时,就必须要保证这个类被加载&这个类已经连接了。而完成上述步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载Java API的那个加载器。
以上就是我对于new关键字、Class.forName()、Class.forName().Instance()三者区别的一点看法。