其他答案非常完整,因为它们探讨了 的其他重载,并讨论了使用不同 ClassLoaders 的可能性。Class.forName(...)
但是,他们没有回答您的直接问题:“上述方法之间有什么区别?”,它涉及一个特定的重载。他们错过了一个非常重要的区别。类初始化。Class.forName(...)
请考虑以下类:
public class A {
static { System.out.println("time = " + System.currentTimeMillis()); }
}
现在考虑以下两种方法:
public class Main1 {
public static void main(String... args) throws Throwable {
final Class<?> c = Class.forName("A");
}
}
public class Main2 {
public static void main(String... args) throws Throwable {
ClassLoader.getSystemClassLoader().loadClass("A");
}
}
第一个类 ,在运行时将生成一个输出,例如Main1
time = 1313614183558
但是,另一个将根本不产生任何输出。这意味着类虽然已加载,但尚未初始化(即,它尚未被调用)。实际上,您甚至可以在初始化之前通过反射来查询类的成员!A
<clinit>
你为什么会关心?
有些类在初始化时执行某种重要的初始化或注册。
例如,JDBC 指定由不同提供程序实现的接口。要使用MySQL,您通常要执行.也就是说,加载并初始化该类。我从未见过该代码,但显然该类的静态构造函数必须在JDBC的某个地方注册该类(或其他东西)。Class.forName("com.mysql.jdbc.Driver");
如果这样做,您将无法使用 JDBC,因为 altough loaded 类尚未初始化(然后 JDBC 将不知道要使用哪个实现,就像您没有加载该类一样)。ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");
因此,这就是您询问的两种方法之间的差异。