Class.forName的作用

本文深入探讨了Java中Class.forName方法的工作原理,特别是其在JDBC连接数据库过程中的作用。通过对比两种不同的驱动注册方式,解释了该方法如何初始化MySQL驱动并进行数据库连接。

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

(本文是从其他网站cope过来的)

今天在看JDBC的时候,就有一个有趣的地方,之前学的时候,也没在意。这个Class.forName究竟什么的英文鬼。

连接数据库几大步。看以下代码

import com.mysql.jdbc.Driver;
  
import java.sql.*;
  
public class JdbcDemo {
  
 public static void main(String[] args) throws SQLException, ClassNotFoundException {
  String url = "jdbc:mysql://127.0.0.1:3306/mydb";
  String username = "root";
  String password = "redhat";
  Class.forName("com.mysql.jdbc.Driver");
  Connection connection = DriverManager.getConnection(url, username, password);
  String sql = "SELECT * FROM msg";
  PreparedStatement prepareStatement = connection.prepareStatement(sql);
  ResultSet resultSet = prepareStatement.executeQuery();
  resultSet.next();
  String address = resultSet.getString("address");
  System.out.println(address);
 }
}
其中第一步,搞的我有点想不通。为啥Class.forName传入了一段字符串之后,就知道我连接的数据库是MySQL的?有点不科学啊。Class.forName到底做了啥。下面就开始到源码中,一探究竟。
@CallerSensitive
public static Class<?> forName(String className)
   throws ClassNotFoundException {
 Class<?> caller = Reflection.getCallerClass();
 return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

它发现了调用forName0方法,继续跟踪再看看

private static native Class<?> forName0(String name, boolean initialize,
          ClassLoader loader,
          Class<?> caller)
 throws ClassNotFoundException;

native方法,源码也只能到此结束了。看下官方文档,怎么说吧。

https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)

发现官方文档,还是描述的很清楚的。

Returns the Class object associated with the class or interface with the given string name,
 using the given class loader. 
Given the fully qualified name for a class or interface (in the same format returned by getName)
 this method attempts to locate, load, and link the class or interface. 
The specified class loader is used to load the class or interface. 
If the parameter loader is null, the class is loaded through the bootstrap class loader.
 The class is initialized only if the initialize parameter is true and if it has not been 
initialized earlier.
嗯,描述的还算是很清楚。报道查看一个给定类或者接口的一个Class对象,如果没有给定classloader,那么会使用根类加载器。如果initalize这个参数传了true,那么给定的类如果之前没有被初始化过,那么会被初始化。我们在JDBC第一步的时候,传入的参数是com.mysql.jdbc.Driver也就是说这个类会被初始化。我们看一下这个类里面的内容。

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!");
  }
 }
  
  
 public Driver() throws SQLException {
  // Required for Class.forName().newInstance()
 }
}

我们发现这个类也是超级简单的。一个构造函数和一个静态代码块。我们知道,类在初始化的时候,静态代码块的内容会被执行的。我们也就是说Class.forName状语从句:直接写DriverManager.registerDriver(new Driver)两者功能的英文等同的。我们换成这种写法。再试试看。

public class JdbcDemo {
  
 public static void main(String[] args) throws SQLException, ClassNotFoundException {
  String url = "jdbc:mysql://127.0.0.1:3306/mydb";
  String username = "root";
  String password = "redhat";
  //Class.forName("com.mysql.jdbc.Driver");
  DriverManager.registerDriver(new Driver());
  Connection connection = DriverManager.getConnection(url, username, password);
  String sql = "SELECT * FROM msg";
  PreparedStatement prepareStatement = connection.prepareStatement(sql);
  ResultSet resultSet = prepareStatement.executeQuery();
  resultSet.next();
  String address = resultSet.getString("address");
  System.out.println(address);
 }
}

发现代码,还是正常的执行了。

总结一下:

Class.forName方法的作用,就是初始化给定的类。而我们给定的的MySQL的驱动程序类中,它在静态代码块中通过JDBC的DriverManager注册了一下驱动。我们也可以直接使用JDBC的驱动管理器注册的MySQL驱动。从而代替使用Class.forName

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助。

<think>Class.forName是 Java反射机制中的一个重要方法,用于动态加载类。它的主要作用是:1.加载指定的类到JVM中(如果该类尚未被加载)。2.执行该类的静态初始化块(staticinitializers)和静态变量赋值。###简洁说明:`Class.forName(StringclassName)`方法通过类的全限定名(包括包路径)加载类,并返回该类的 `Class`对象。在加载过程中,它会触发类的静态初始化块(static块)的执行。###示例代码: ```javapublic classClassForNameExample{public staticvoid main(String[]args){try{//加载类并触发静态初始化块Class<?> clazz =Class.forName("com.example.MyClass");System.out.println("类加载成功:" +clazz.getName());}catch (ClassNotFoundExceptione){e.printStackTrace();}} }class MyClass {static{System.out.println("MyClass的静态初始化块被执行");} }``` ###解释: -当调用 `Class.forName("com.example.MyClass")`时,JVM会查找并加载名为`MyClass`的类。-在加载过程中,如果类中有静态初始化块(`static {... }`),则会被执行。上面的例子中,`MyClass`的静态块会输出一条消息。 -如果类不存在,会抛出 `ClassNotFoundException`。###重载方法:`Class.forName`还有一个重载方法: ```javaClass.forName(Stringname, booleaninitialize,ClassLoaderloader)``` -`name`:类全限定名。- `initialize`:是否进行初始化(即是否执行静态块)。如果为`true`,则执行静态初始化;如果为 `false`,则不会执行静态初始化。- `loader`:指定类加载器。 ###常见用途: 1. **数据库驱动注册**:在JDBC中,通过`Class.forName("com.mysql.jdbc.Driver")`加载驱动类,该类的静态块会向 `DriverManager`注册驱动。 2. **动态加载类**:在框架中根据配置加载类,如 Spring框架中根据类名创建Bean。###注意事项:-使用 `Class.forName`会触发类的初始化(执行静态块),而直接使用 `ClassLoader.loadClass`不会触发初始化(只加载类,不执行静态块)。-需要处理`ClassNotFoundException`异常。###示例:JDBC驱动加载```java//传统JDBC驱动加载方式Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接Connection conn= DriverManager.getConnection(url, user, password); ```在 MySQL驱动类的静态初始化块中,会创建一个`Driver`实例并注册到`DriverManager`。###总结:`Class.forName`是一个强大的反射工具,用于动态加载类并初始化。它常用于需要运行时加载类的场景,如框架设计、插件系统、数据库驱动加载等。--- §§相关问题§§: 1. `Class.forName`和`ClassLoader.loadClass`有什么区别? 2.在 Java中,类的加载过程包括哪些步骤? 3.如何通过反射实例化一个类?4.静态初始化块在什么情况下会被执行?</think>### Class.forName作用简洁说明 `Class.forName(String className)` 是 Java 反射机制的核心方法之一,主要作用是通过类的**全限定名**(包含包路径的完整类名)动态加载类到 JVM 中,并触发类的**静态初始化块**(static 代码块)的执行。它返回一个 `Class` 对象,该对象包含类的元数据信息。 #### 核心作用: 1. **动态加载类**:运行时根据字符串形式的类名加载类(无需在代码中显式 import)。 2. **执行静态初始化**:触发类的 `static { ... }` 代码块(如 JDBC 驱动注册)。 3. **获取类的元信息**:返回 `Class` 对象用于后续反射操作(如实例化、调用方法等)。 --- ### 代码示例与解释 ```java public class ClassForNameDemo { public static void main(String[] args) { try { // 动态加载类并触发静态初始化 Class<?> clazz = Class.forName("com.example.MyClass"); System.out.println("类加载成功: " + clazz.getName()); // 通过反射实例化对象 Object instance = clazz.getDeclaredConstructor().newInstance(); System.out.println("实例创建成功: " + instance); } catch (ClassNotFoundException e) { System.err.println("类未找到: " + e.getMessage()); } catch (Exception e) { e.printStackTrace(); } } } // 被加载的类 class MyClass { // 静态初始化块(Class.forName 时会执行) static { System.out.println("MyClass 的静态初始化块已执行!"); } public MyClass() { System.out.println("MyClass 的构造函数被调用"); } } ``` #### 执行结果: ``` MyClass 的静态初始化块已执行! 类加载成功: com.example.MyClass MyClass 的构造函数被调用 实例创建成功: com.example.MyClass@1b6d3586 ``` #### 关键点解释: 1. **`Class.forName("com.example.MyClass")`** - 通过全限定名加载类,触发 `static` 代码块(输出第一行)。 - 返回 `Class<?>` 对象用于后续反射操作。 2. **`clazz.getDeclaredConstructor().newInstance()`** - 利用反射创建类实例(调用构造函数)。 3. **异常处理** - `ClassNotFoundException`:类路径配置错误或类不存在。 - 其他异常:反射操作失败(如无参构造函数不可访问)。 --- ### 典型应用场景 1. **JDBC 驱动注册**(经典用法): ```java Class.forName("com.mysql.cj.jdbc.Driver"); // Driver 类的静态块会向 DriverManager 注册自己 ``` 2. **插件化架构**:动态加载实现类(如通过配置文件指定类名)。 3. **框架设计**:Spring 等框架的 IoC 容器中动态实例化 Bean。 --- ### 注意事项 1. **类名必须全限定**:`com.example.MyClass` 而非 `MyClass`。 2. **依赖 JVM 类路径**:类需在 `classpath` 中可访问。 3. **初始化控制**:重载方法 `Class.forName(String, boolean, ClassLoader)` 的第二个参数可控制是否执行静态初始化。 4. **性能开销**:反射操作比直接调用慢,高频场景需谨慎使用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值