从Class.forName想到的……

本文详细解析了Class.forName的作用及其在Java中的具体应用,包括如何利用其将类加载到JVM中,以及它在创建对象、工厂模式、Spring依赖注入等场景中的运用。通过对比直接new关键字的使用,阐述了Class.forName带来的灵活性和便利性,强调了参数传递带来的变化多样性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Class.forName是“用来加载类的”,其实这话还是有点抽象,更加具体的说就是“用来将类加载到jvm中”,这样就清楚许多了。

我们都知道,所有的class文件都要加载到jvm中才可以得到运行,所以当我们需要加载一个类时就可以用Class.forName将这个类加载到jvm中。下面两个语句:

A a = (A)Class.forName("pacage.A").newInstance();

A a = new A();

都是创建包package中类A的一个对象a。这两种写法爱用哪种就用哪种,当然可以发现,我们用的最多的还是直接new吧!很少人问为什么,虽然很多人在使用jdbc干活的时候读用到了Class.forName这句代码。

我们观察第一个创建对象的方式,它有一个最大的好处就是类名可以作为参数的形式传入,然后创建对象。这使得一个简单的new可以分为两步进行:

1、第一步

Class temp = Class.forName("pacage.A");;

2、第二步

A a = temp.newInstance();

看到了吧,一个简单的new可以分解为两步,而这里关键的参数是最重要的,我们说“有参数就有变化”,这个参数带来的变化是千变万化的。

工厂模式相信大家伙都知道,Spring的DI就是一个很好的工厂模式,当我们使用Spring进行开发时,new语句已经不出现了,那么对象怎么创建的呢?对就是用的Class.forName进行的。这也就是为什么我们在使用Spring的时候常常要在配置文件里面将类的路径配置的完完当当的。

就这么一个简单的new, Java就将其设计为两种方式了,而Class.forName的方式实在是让我叫绝。

真的是“多一个参数就多了一个精彩啊”,这里面的“玄机”需要好好的感悟……

### Java `Class.forName` 方法详解 #### 什么是 `Class.forName` `Class.forName()` 是 Java 提供的一个静态方法,位于 `java.lang.Class` 中。此方法接受一个字符串参数作为的全限定名(即包路径加上类名),并返回对应的 `Class` 对象实例[^1]。 ```java // 加载名为 "com.example.MyClass" 的 Class<?> clazz = Class.forName("com.example.MyClass"); ``` 该调用不仅会加载目标JVM 虚拟机内存空间内,还会初始化此——这意味着任何声明于其中的静态成员变量都将被赋予初始值,并且所有的静态代码块会被执行一次[^4]。 #### 基本语法与示例 最简单的形式如下所示: ```java String className = "com.example.MyClass"; try { Class<?> myClass = Class.forName(className); } catch (ClassNotFoundException e) { System.err.println(e.getMessage()); } ``` 如果希望创建新实例,则可以进一步结合反射 API 使用: ```java Object instance; try { Class<?> myClass = Class.forName("com.example.MyClass"); Constructor<?> constructor = myClass.getConstructor(); instance = constructor.newInstance(); } catch (Exception e) { System.err.println(e.getMessage()); } ``` 需要注意的是,在较新的 JDK 版本里推荐使用带有额外参数的形式来显式指定是否要触发初始化以及自定义加载器[^2]。 #### 反射特性支持 借助 `Class.forName()`, 开发者能够实现更加灵活的应用程序设计模式,比如插件化架构或是数据库连接池管理工具等。这是因为一旦获得了代表某个型的 `Class` 实例之后,便可以通过它访问到几乎一切关于这个型的信息,包括但不限于字段、构造函数和公共/私有方法等。 例如,当应用程序启动时自动注册 JDBC 驱动程序就是利用了这一功能;只需简单地调用 `Class.forName(driverClassName)` 即可完成驱动加载工作,因为大多数 SQL 数据库提供商都会在其内部定义相应的静态初始化逻辑[^3]。 #### 常见问题解答 - **为什么有时候需要手动调用 `Class.forName()`?** 这通常是为了延迟加载某些资源直到真正需要用到的时候才去处理它们,从而提高性能或减少不必要的依赖关系引入。另外一种情况是在编写通用框架时为了保持良好的扩展性和兼容性而采用的方式之一。 - **如何区分 `Class.forName()` 和 `ClassLoader.loadClass()` ?** 尽管两者都可以用来动态加载文件,但是前者默认情况下会对所加载的目标进行初始化操作(除非指定了第三个布尔型参数为 false),而后者的标准行为则是仅限于查并读取字节码而不做其他动作。 - **遇到 `ClassNotFoundException` 怎么办?** 此异常表明虚拟机未能到请求加载的那个特定。可能的原因有很多,像是拼写错误、缺少必要的 JAR 文件或者是版本冲突等问题都可能导致这个问题的发生。建议仔细检查项目的构建配置和运行环境设置以排除这些潜在隐患。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值