千家信息网

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

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,这篇文章给大家分享的是有关在Java的反射中Class.forName和ClassLoader有哪些区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。解释在java中Cla
千家信息网最后更新 2025年02月03日在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安全错误 数据库的锁怎样保障安全 网络安全资讯网站 浪潮服务器厂商电话 论文里数据库的表应该是什么样 网络安全答题题库150题 mysql数据库如何使用 浙江省网络安全产业报告 服务器浮点运算值怎么计算 网络安全红队技术能力标准 安可服务器报价 全国小学生网络安全知识 常州移动软件开发 深圳犇牛网络技术有限公司 围绕爱国和网络安全意识 有趣网络安全教育班会ppt 数据库要不要外键约束 河北区网络安全信息化委员会 网络安全产业市场 微信小程序租赁服务器源码 网络安全技术实务第六章第一节 广东国内网络技术开发商家 我的世界内置服务器有什么用 首选dns服务器地址河北 零基础学软件开发还是测试 通信网络安全原理与实践 电脑下载摩尔庄园是哪个服务器 要做软件开发需要准备什么 远程桌面服务器授权 戴尔服务器无法识别32g内存 网络安全策略概括 重阳服务器
0