java中Class.forName方法的作用详解

 更新时间:2017年06月29日 11:06:41   作者:honway  
Class.forName(xxx.xx.xx) 返回的是一个类,但Class.forName方法的作用到底是什么終?下面这篇文章就来给大家详细介绍了关于java中Class.forName方法的作用,文中介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。

前言

在做JAVA EE开发的过程中,更多的是使用框架来提高开发效率.越来越发现,之前很基础的一些东西,都忘记的差不多了.从今天开始慢慢的复习一下基础.今天在看JDBC的时候,就有一个有趣的地方,之前学的时候,也没在意.这个Class.forName究竟是什么鬼.

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

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 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的Driver类中,它在静态代码块中通过JDBC的DriverManager注册了一下驱动.我们也可以直接使用JDBC的驱动管理器注册mysql驱动.从而代替使用Class.forName.

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • springboot中.yml文件的值无法读取的问题及解决

    springboot中.yml文件的值无法读取的问题及解决

    这篇文章主要介绍了springboot中.yml文件的值无法读取的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 使用JPA进行CriteriaQuery进行查询的注意事项

    使用JPA进行CriteriaQuery进行查询的注意事项

    这篇文章主要介绍了使用JPA进行CriteriaQuery进行查询的注意事项,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 关于@Autowierd && @Resource 你真的了解吗

    关于@Autowierd && @Resource 你真的了解吗

    这篇文章主要介绍了关于@Autowierd && @Resource的具体使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 一文带你弄懂Maven拉包(拉取依赖包)原理

    一文带你弄懂Maven拉包(拉取依赖包)原理

    业务需求开发的时候,我们总是会遇到拉不到依赖包的情况,此时如果不清楚 Maven 拉取依赖包的原理,那么很可能找不到问题所在,今天小编就带大家了解下 Maven 拉包的原理,让你在遇到问题的时候能快速解决,需要的朋友可以参考下
    2023-07-07
  • SpringBoot项目整合Redis教程详解

    SpringBoot项目整合Redis教程详解

    这篇文章主要介绍了SpringBoot项目整合Redis教程详解,Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。感兴趣的小伙伴可以参考阅读本文
    2023-03-03
  • java8 计算时间差的方法示例

    java8 计算时间差的方法示例

    这篇文章主要介绍了java8 计算时间差的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • 关于QueryWrapper高级使用示例

    关于QueryWrapper高级使用示例

    本文介绍了QueryWrapper的高级使用方法,包括查询指定字段、使用MySQL函数处理字段、设置查询限制等,通过select()可查询指定字段并处理,last()方法实现limit效果,apply()可在查询条件中使用函数,这些技巧有助于提升数据库操作的灵活性和效率
    2024-09-09
  • springboot读取配置文件中的参数具体步骤

    springboot读取配置文件中的参数具体步骤

    在本篇文章里小编给大家分享了关于springboot读取配置文件中的参数的相关知识点内容,有需要的朋友们跟着学习下。
    2019-06-06
  • Resty开发restful版本的Jfinal深入研究

    Resty开发restful版本的Jfinal深入研究

    这篇文章主要为大家介绍了Resty开发restful版本的Jfinal深入研究有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • Java文件操作实例详解

    Java文件操作实例详解

    这篇文章主要为大家详细介绍了Java文件操作实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论