public class TestObject {
static {
System.out.println("我已经成功初始化。");
}
}
public class TestDriver {
public static void main(String[] args) {
try {
//1. 使用Class.forName加载
//Class.forName(TestObject.class.getName());
//2. 使用loader.load加载
ClassLoader loader=TestDriver.class.getClassLoader();
loader.loadClass(TestObject.class.getName());
//3. 使用new Object
//TestObject object=new TestObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
1.使用Class.forName加载
输出:我已经成功初始化。
2.使用loader.load加载
没有任何输出
3.使用new Object
输出:我已经成功初始化。
我们知道Java在加载的过程将经过这么几个步骤。
从上面的结果,我们可以看出,其实Class.forName与new Object的方法已经完成了类的初始化,但是ClassLoader.loadClass只是完成了类的加载。之所以要加载类是因为JVM并不是在项目运行时就把所有的类文件加载到JVM,而是当类需要的的时候,才去加载。
加载就是通过类的全限定名获取二进制字节流,将二进制字节流转成方法区中运行的数据结构,在内存中生成Java.lang.class对象。
Class.forName(className)法实际上调用的方法是Class.forName0(className, true, ClassLoader.getClassLoader(caller), caller),第二个参数boolean代表类是否需要被初始化。
ClassLoader.loadClass(className)方法实际上调用的方法是ClassLoader.loadClass(name, false),第二个参数boolean代表的是类是否进行链接。
从上面可以看出,ClassLoader.loadClass(className)默认是不链接的,意味着,静态方法将无法被执行。
我们第一次认识Class.forName,可能是在写数据库连接的时候。那时候,我就按照教程写,很轻松就拿到了连接。
现在,我们来分析一下JDBC驱动装载过程:
当我们写
Class.forName(“com.MySQL.jdbc.Driver”);
com.MySQL.jdbc.Driver将被初始化,这时候,调用了com.MySQL.jdbc.Driver静态初始化块
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can\'t register driver!");
}
}
向DriverManager注册了这个驱动。
public static synchronized void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
驱动被添加到了registeredDrivers。
综上,不能使用ClassLoader.loadClass。
这两者的区别就是new Object可以构造带参构造器。