Class.forName的含义

Class.forName(xxx.xx.xx) 返回的是一个类, .newInstance() 后才创建一个对象 Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段


Class aClass = Class.forName(xxx.xx.xx);
Object anInstance = aClass.newInstance();


Class.forName("").newInstance()返回的是object
but there is some limit for this method to create instance
that is your class constructor should no contain parameters, and you should cast the instance manually.

Class Driver{
protected static Driver current;
public static Driver getDriver(){
return current;
}
}

Class MyDriver extends Driver{
static{
Driver.current=new MyDriver();
}
MyDriver(){}
}

用时:
Class.forName("MyDriver");
Driver d=Driver.getDriver();

有的jdbc连接数据库的写法里是Class.forName(xxx.xx.xx);而有一些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?

Class.forName(xxx.xx.xx) 返回的是一个类,
.newInstance() 后才创建一个对象

Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC Driver的Driver类的代码都必须类似如下:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}

所以我们在使用JDBC时只需要Class.forName(XXX.XXX);就可以了

we just want to load the driver to jvm only, but not need to user the instance of driver, so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(), the result will same as calling Class.forName(xxx.xx.xx), because Class.forName(xxx.xx.xx).newInstance() will load driver first, and then create instance, but the instacne you will never use in usual, so you need not to create it.

在JDBC驱动中,有一块静态代码,也叫静态初始化块,它执行的时间是当class调入到内存中就执行(你可以想像成,当类调用到内存后就执行一个方法)。所以很多人把jdbc driver调入到内存中,再实例化对象是没有意义的。
<think>我们正在讨论Java中的Class.forName方法。根据引用[1],Class.forName是Java反射机制中的重要方法,用于动态加载类并初始化类的字节码。它在框架开发和底层实现中常见,如JDBC驱动加载和动态代理。 引用[2]指出,Class.forName(xxx)返回的是一个类,调用.newInstance()后才会创建一个对象。它的作用是要求JVM查找并加载指定的类,并且会执行该类的静态代码段。 引用[3]强调,Class.forName用于装载类,而new是根据加载到内存中的类创建一个实例。它常用于需要根据字符串变量(代表类的全限定名)来实例化对象的情况。 引用[4]补充了细节:Class.forName(String name)生成指定类名的类对象(Class对象),等同于Class.forName(className, true, currentLoader),其中第二个参数true表示会进行类的初始化(即执行静态代码块)。同时,它描述了类加载过程:通过全限定名获取类的二进制字节流,并将字节流转化为方法区的运行时数据结构。特别提到,生成Class对象后,会执行静态块代码,如MySQL驱动的加载。 因此,我们可以总结: 1. Class.forName的主要作用是动态加载类到JVM中,并返回一个Class对象。 2. 在加载过程中,如果指定了初始化(默认情况),则会执行该类的静态初始化块(static块)和静态变量的初始化。 3. 通常,我们使用它来加载那些在编译时无法确定,但在运行时通过字符串形式给出的类。 下面,我将详细解释Class.forName含义、使用方法和注意事项,并给出代码示例。 ### 1. Class.forName的基本用法 `Class.forName` 是一个静态方法,它有两种重载形式: - `Class<?> forName(String className)` - `Class<?> forName(String name, boolean initialize, ClassLoader loader)` 我们常用的是第一种形式,它等同于 `Class.forName(className, true, currentLoader)`,即会进行初始化(执行静态块),并使用当前类的类加载器。 示例:加载一个类并执行其静态块 ```java public class Test { static { System.out.println("静态初始化块执行"); } } public class Main { public static void main(String[] args) throws ClassNotFoundException { Class<?> clazz = Class.forName("Test"); } } ``` 运行Main类,输出:"静态初始化块执行"。 ### 2. 为什么需要Class.forName? 在Java中,类是在第一次使用时动态加载的。通常,我们通过new关键字创建一个对象时,类会被加载。但有时我们无法在编译时知道具体的类名,而是通过字符串形式在运行时获取。例如: - 数据库驱动加载:在JDBC中,我们使用`Class.forName("com.mysql.cj.jdbc.Driver")`来加载驱动,驱动的静态块中会向DriverManager注册自己。 - 框架中根据配置文件的类名动态加载类(如Spring框架的IoC容器)。 ### 3. 与newInstance()结合创建对象 通过Class.forName获得Class对象后,我们可以调用`newInstance()`方法来创建该类的实例(要求类必须有一个无参构造器): ```java Class<?> clazz = Class.forName("com.example.MyClass"); Object obj = clazz.newInstance(); // 相当于调用无参构造器 ``` 注意:从Java 9开始,`newInstance()`方法被标记为过时,推荐使用`clazz.getDeclaredConstructor().newInstance()`。 ### 4. 关于初始化 当我们使用`Class.forName(className, false, loader)`时,第二个参数为false,则不会执行静态初始化块。这在某些特殊场景下有用,比如我们只需要加载类而不希望触发静态块。 ### 5. 注意事项 - 类名必须是全限定名(包含包名),例如`java.lang.String`。 - 该方法会抛出`ClassNotFoundException`,因此需要处理异常。 - 初始化静态块时,如果静态块中有复杂的操作或异常,可能会导致加载失败。 ### 6. 代码示例:JDBC驱动加载 在JDBC中,我们通常这样加载驱动: ```java Class.forName("com.mysql.cj.jdbc.Driver"); ``` 这是因为在`Driver`类中有一个静态初始化块: ```java public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } // ... } ``` 当调用`Class.forName`时,静态块执行,将驱动注册到`DriverManager`中。 ### 总结 `Class.forName` 是Java反射机制中用于动态加载类的方法,它会执行类的静态初始化块(默认情况下)。主要应用场景包括: - 动态加载类(尤其当类名来自配置、字符串变量时) - 框架开发(如JDBC驱动加载、动态代理等) 但要注意,它只加载类并初始化静态部分,创建对象需要另外调用`newInstance()`(或通过构造器)。 §§相关问题§§ 1. Java中Class.forNameClassLoader.loadClass有什么区别? 2. 为什么JDBC驱动加载需要用Class.forName? 3. Java反射中,除了Class.forName,还有哪些方式可以获取Class对象? 4. Class.forName在加载类时会触发哪些类加载阶段? </think>### Java 中 `Class.forName()` 的含义详解 `Class.forName()` 是 **Java 反射机制的核心方法**,用于动态加载并初始化类的字节码。以下是其核心含义和原理: #### 一、核心作用 1. **动态加载类** 根据**字符串形式的全限定类名**(如 `"java.lang.String"`)查找并加载该类到 JVM 中,返回对应的 `Class` 对象[^1][^2]。 ```java Class<?> clazz = Class.forName("com.example.MyClass"); // 加载类 ``` 2. **触发类初始化**(默认行为) 默认情况下(即 `Class.forName(className)`),会**执行类的静态初始化块(static 代码块)和静态变量赋值**[^2][^4]。 例如 JDBC 驱动注册: ```java Class.forName("com.mysql.cj.jdbc.Driver"); // 触发 Driver 类中的 static { DriverManager.registerDriver(new Driver()); } ``` 3. **与 `new` 关键字的区别** - `Class.forName()` 仅**加载类并初始化静态成员**,但不创建对象实例[^2][^3]。 - 创建对象需额外调用 `clazz.newInstance()`(已废弃)或 `clazz.getConstructor().newInstance()`: ```java Object obj = clazz.getDeclaredConstructor().newInstance(); // 创建实例 ``` --- #### 二、关键参数解析 方法签名: `Class<?> forName(String name, **boolean initialize**, ClassLoader loader)` - **`initialize` 参数**(默认为 `true`) - `true`:执行类的静态初始化(static 块)[^4]。 - `false`:仅加载类到内存,**不执行静态初始化**(适用于避免副作用场景)。 - **`ClassLoader` 参数** 指定类加载器,默认使用当前类的加载器。 --- #### 三、典型应用场景 1. **JDBC 驱动加载** 通过静态块自动向 `DriverManager` 注册驱动[^1]: ```java Class.forName("com.mysql.cj.jdbc.Driver"); // 静态块中注册驱动 ``` 2. **动态扩展功能** 根据配置文件动态加载实现类(如插件化架构): ```java String className = config.getProperty("serviceImpl"); Service service = (Service) Class.forName(className).newInstance(); ``` 3. **框架开发** Spring、Hibernate 等框架利用此方法实现依赖注入和动态代理[^1]。 --- #### 四、注意事项 1. **必须处理 `ClassNotFoundException`** 当类不存在时抛出该异常: ```java try { Class<?> clazz = Class.forName("InvalidClassName"); } catch (ClassNotFoundException e) { // 处理找不到类的情况 } ``` 2. **性能影响** 反射操作比直接调用慢,高频场景需谨慎使用。 3. **替代 `newInstance()`** Java 9+ 推荐使用构造器创建实例: ```java Object obj = clazz.getDeclaredConstructor().newInstance(); ``` --- ### 总结 | **核心特性** | **说明** | |----------------------|--------------------------------------------------------------------------| | **动态加载** | 通过字符串类名加载类到 JVM | | **触发静态初始化** | 默认执行 static 代码块(可通过 `initialize=false` 关闭) | | **返回 Class 对象** | 获取类元信息(方法、字段等),为反射操作提供入口 | | **与实例化分离** | 加载类 ≠ 创建对象,需额外调用构造器 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值