Java中的Class.forName
在做JAVA EE开发的过程中,更多的是使用框架来提高开发效率.越来越发现,之前很基础的一些东西,都忘记的差不多了.从今天开始慢慢的复习一下基础.今天在看JDBC的时候,就有一个有趣的地方,之前学的时候,也没在意.这个Class.forName究竟是什么鬼.
连接数据库几大步.看以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import com.mysql.jdbc.Driver; import java.sql.*; /** * @author honway.liu * @date 2016/12/8 下午11:07 * @email gm100861@gmail.com * @blog http://linuxsogood.org */ public class JdbcDemo { public static void main(String[] args) throws SQLException, ClassNotFoundException { 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); } } |
1 | 其中第一步,搞的我有点想不通.为啥Class.forName传入了一段字符串之后,就知道我连接的数据库是mysql? 有点不科学啊.Class.forName到底做了啥.下面就开始到源码中,一探究竟. |
1 2 3 4 5 6 | @CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true , ClassLoader.getClassLoader(caller), caller); } |
发现它调用了forName0方法,继续跟踪再看看
1 2 3 4 | private static native Class<?> forName0(String name, boolean initialize, ClassLoaderloader, Class<?> caller) throws ClassNotFoundException; |
native方法,源码也只能到此结束了.看下官方文档,怎么说吧.
https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)
发现官方文档,还是描述的很清楚的.
1 2 3 4 5 6 7 8 | ReturnstheClass object associatedwiththeclass or interface withthegivenstring name, usingthegivenclass loader. Giventhefullyqualifiednamefor a class or interface (in thesameformatreturnedbygetName) this methodattemptsto locate, load, and linktheclass or interface . Thespecifiedclass loaderis usedto loadtheclass or interface . If theparameterloaderis null , theclass is loadedthroughthebootstrapclass loader. Theclass is initializedonlyif theinitializeparameteris true and if ithasnot been initializedearlier. |
嗯,描述的还算是很清楚.返回一个给定类或者接口的一个Class对象,如果没有给定classloader,那么会使用根类加载器.如果initalize这个参数传了true,那么给定的类如果之前没有被初始化过,那么会被初始化.我们在JDBC第一步的时候,传入的参数是com.mysql.jdbc.Driver. 也就是说这个类会被初始化.我们看一下这个类里面的内容.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Driverextends NonRegisteringDriverimplements 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)两者功能是等同的.我们换成这种写法.再试试看.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class JdbcDemo { public static void main(String[] args) throws SQLException, ClassNotFoundException { 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的Driver类中,它在静态代码块中通过JDBC的DriverManager注册了一下驱动.我们也可以直接使用JDBC的驱动管理器注册mysql驱动.从而代替使用Class.forName.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异