千家信息网

在Java的反射中Class.forName和ClassLoader有哪些区别

发表于:2025-11-16 作者:千家信息网编辑
千家信息网最后更新 2025年11月16日,这篇文章给大家分享的是有关在Java的反射中Class.forName和ClassLoader有哪些区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。解释在java中Cla
千家信息网最后更新 2025年11月16日在Java的反射中Class.forName和ClassLoader有哪些区别

这篇文章给大家分享的是有关在Java的反射中Class.forName和ClassLoader有哪些区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

解释

在java中Class.forName()和ClassLoader都可以对类进行加载。ClassLoader就是遵循 双亲委派模型 最终调用启动类加载器的类加载器,实现的功能是"通过一个类的全限定名来获取描述此类的二进制字节流",获取到二进制流后放到JVM中。Class.forName()方法实际上也是调用的CLassLoader来实现的。

Class.forName(String className);这个方法的源码是

 @CallerSensitive public static Class forName(String className) throws ClassNotFoundException { Class caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }

最后调用的方法是forName0这个方法,在这个forName0方法中的第二个参数被默认设置为了true,true代表是否对加载的类进行初始化,对类进行初始化,代表会执行类中的静态代码块,以及对静态变量的赋值等操作。

也可以调用Class.forName(String name, boolean initialize,ClassLoader loader)方法来手动选择在加载类的时候是否要对类进行初始化。Class.forName(String name, boolean initialize,ClassLoader loader)的源码如下:

 /* @param name fully qualified name of the desired class * @param initialize if {@code true} the class will be initialized. * See Section 12.4 of The Java Language Specification. * @param loader class loader from which the class must be loaded * @return class object representing the desired class * * @exception LinkageError if the linkage fails * @exception ExceptionInInitializerError if the initialization provoked * by this method fails * @exception ClassNotFoundException if the class cannot be located by * the specified class loader * * @see java.lang.Class#forName(String) * @see java.lang.ClassLoader * @since 1.2 */ @CallerSensitive public static Class forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { Class caller = null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { // Reflective call to get caller class is only needed if a security manager // is present. Avoid the overhead of making this call otherwise. caller = Reflection.getCallerClass(); if (sun.misc.VM.isSystemDomainLoader(loader)) { ClassLoader ccl = ClassLoader.getClassLoader(caller); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } return forName0(name, initialize, loader, caller); }

源码中的注释只摘取了一部分,其中对参数initialize的描述是: if {@code true} the class will be initialized. 意思就是说:如果参数为true,则加载的类将会被初始化。

下面还是举例来说明结果吧:

一个含有静态代码块、静态变量、赋值给静态变量的静态方法的类

public class ClassForName { //静态代码块 static { System.out.println("执行了静态代码块"); } //静态变量 private static String staticFiled = staticMethod(); //赋值静态变量的静态方法 public static String staticMethod(){ System.out.println("执行了静态方法"); return "给静态字段赋值了"; }}

测试方法:

public class MyTest { @Test public void test44(){ try { Class.forName("com.test.mytest.ClassForName"); System.out.println("#########分割符(上面是Class.forName的加载过程,下面是ClassLoader的加载过程)##########"); ClassLoader.getSystemClassLoader().loadClass("com.test.mytest.ClassForName"); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}

运行结果:

执行了静态代码块执行了静态方法#########分割符(上面是Class.forName的加载过程,下面是ClassLoader的加载过程)##########

根据运行结果得出Class.forName加载类是将类进了初始化,而ClassLoader的loadClass并没有对类进行初始化,只是把类加载到了虚拟机中。

在我们熟悉的Spring框架中的IOC的实现就是使用的ClassLoader。

而在我们使用JDBC时通常是使用Class.forName()方法来加载数据库连接驱动。这是因为在JDBC规范中明确要求Driver(数据库驱动)类必须向DriverManager注册自己。

以MySQL的驱动为例解释:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {  // ~ Static fields/initializers  // ---------------------------------------------   //  // Register ourselves with the DriverManager  //  static {  try {  java.sql.DriverManager.registerDriver(new Driver());  } catch (SQLException E) {  throw new RuntimeException("Can't register driver!");  }  }   // ~ Constructors  // -----------------------------------------------------------   /**  * Construct a new driver and register it with DriverManager  *  * @throws SQLException  * if a database error occurs.  */  public Driver() throws SQLException {  // Required for Class.forName().newInstance()  } }

我们看到Driver注册到DriverManager中的操作写在了静态代码块中,这就是为什么在写JDBC时使用Class.forName()的原因了。

感谢各位的阅读!关于"在Java的反射中Class.forName和ClassLoader有哪些区别"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

静态 方法 代码 变量 就是 过程 参数 源码 结果 驱动 反射 二进制 代表 内容 数据 数据库 更多 篇文章 解释 运行 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 维护网络安全从我做起画报 服务器 屏蔽某省份 访问 无人驾驶汽车5g网络安全吗 我的服务器被办了 用英语怎么说 怎样注册泰拉瑞亚服务器 网络安全评估方案 2021年网络安全培训心得 如何追究软件开发商责任 汉中网络安全宣传周 服务器保修时间 软件开发工程师和自动化哪个好 ftp资源服务器搭建 网络技术开发进度查询服务平台 上海有机化学数据库访问不了 荣耀60无法连接服务器 软件开发企业税收筹划案例 导出数据库某个表数据 宁夏政府网络安全研究院 dhcp服务器是什么意思 全国开源应用软件开发大赛 厦门软件开发外包公司哪家好 益阳串口服务器费用 网页链接服务器 致网络技术有限公司 飞秋数据库在哪 服务器爆满有没有办法挤进去王者 校园网络安全问题该如何应对 英雄联盟俄罗斯服务器在哪 服务器安全 磁盘镜像 数据库视图如何加字段
0