Class.forName和ClassLoader.loadClass在类加载时有何不同?
参考回答
Class.forName()
和 ClassLoader.loadClass()
都是用来加载类的方法,但它们的使用场景和行为有所不同。具体区别如下:
Class.forName()
:- 这是一个静态方法,用于加载指定名称的类。
- 默认情况下,
Class.forName()
会触发类的初始化(即执行类中的静态代码块)。 - 它通常用于加载并初始化类,尤其是在反射和 JDBC 等场景中很常见。
ClassLoader.loadClass()
:- 这是
ClassLoader
类的一个实例方法,用于加载类。 - 它不会主动触发类的初始化,只会加载类的字节码。
- 需要显式调用
class.getClassLoader().loadClass()
或通过自定义类加载器来使用。
- 这是
以下是一个简单的示例,展示了 Class.forName()
和 ClassLoader.loadClass()
的区别:
详细讲解与拓展
Class.forName()
:- 静态方法:
Class.forName()
是Class
类的静态方法,它接收一个字符串参数,表示类的全限定名(例如com.example.MyClass
)。它会使用当前线程的上下文类加载器来加载该类。 - 初始化类:
Class.forName()
不仅加载类的字节码,还会执行类的静态初始化(即类中的静态块和静态字段的初始化)。例如,如果该类中有静态代码块或静态变量,Class.forName()
会自动执行这些代码。
例如,以下代码:
当使用
Class.forName("com.example.MyClass")
加载MyClass
时,静态代码块会被执行并输出"Static block in MyClass"
。- 静态方法:
-
ClassLoader.loadClass()
:- 实例方法:
loadClass()
是ClassLoader
类的实例方法,通常用于加载类。它不会直接触发类的初始化,仅仅是加载字节码。 - 类初始化控制:
loadClass()
会先调用父类加载器的loadClass()
方法来尝试加载类,符合双亲委派模型。即使类加载成功,类的静态初始化(静态代码块)不会自动执行。要显式地触发初始化,需要调用Class.forName()
或通过clazz.getDeclaredConstructor().newInstance()
来创建该类的实例。
例如,以下代码:
当使用
ClassLoader.loadClass("com.example.MyClass")
加载类时,静态代码块不会被执行。 - 实例方法:
-
常见使用场景:
Class.forName()
:- 主要用于加载并初始化类,常见于 JDBC(数据库连接),例如加载数据库驱动类。
- 例如:
Class.forName("com.mysql.cj.jdbc.Driver")
会加载并初始化 MySQL JDBC 驱动类。
ClassLoader.loadClass()
:- 通常用于自定义类加载器或动态加载类的场景,控制加载过程。
- 适用于需要仅加载类而不立即初始化的情况。
补充说明:
- 类的初始化:
- 在 Java 中,类的初始化是通过执行类的静态代码块、初始化静态变量等来完成的。
Class.forName()
会触发类的初始化,而ClassLoader.loadClass()
默认不会。
- 在 Java 中,类的初始化是通过执行类的静态代码块、初始化静态变量等来完成的。
- 双亲委派模型:
- 在使用
ClassLoader.loadClass()
时,通常会遵循双亲委派模型,即子类加载器会将加载请求委派给父类加载器。这个机制有助于保证 Java 的核心类库不被覆盖。
- 在使用
总结
Class.forName()
是一个静态方法,加载类并触发类的初始化;ClassLoader.loadClass()
是实例方法,只加载类的字节码,不会触发初始化。Class.forName()
适用于需要加载并初始化类的场景,而ClassLoader.loadClass()
更适用于加载类但不立即初始化的场景。- 两者在处理类的初始化和加载机制上有明显差异,需要根据实际需求选择使用。
阅读全文
人机验证(防爬虫)
扫码关注公众号:帅地玩编程
发送: 验证码
提醒:提交验证后记得刷新当前页面

提交