zoukankan      html  css  js  c++  java
  • [改善Java代码]使用forName动态加载类文件

    动态加载(Dynamic Loading)是指在程序运行时加载需要的类库文件,对Java程序来说,一般情况下,一个类文件在启动时或首次初始化时会被加载到内存中,而反射则可以在运行时再决定是否需要加载一个类,比如从Web上接受一个String参数作为类名,然后在JVM中加载并初始化,这就是动态加载,此动态加载通常是通过Class.forName(String)实现的,只是这个forName()方法到底是什么意思?

    我们知道一个类文件只有在被加载到内存中后才可能生成实例对象,也就是说一个对象的生成必然会经过以下两个步骤:

    1.加载到内存中生成Class的实例对象.

    2.通过new关键字生成实例对象.

    如果我们使用的是import关键字产生的依赖包,JVM在启动时会自动加载所有依赖包下的类文件,这没有什么问题,如果要动态加载一个类文件呢?就需要使用forName方法了.

    为什么要使用forName()方法动态加载一个类文件呢?那是因为我们不知道生成的实例对象是什么类型(如果知道就不用动态加载).而且方法和属性都不可访问.

    动态加载的意义是什么?

    意义在于:加载一个类,即表示要初始化该类的static变量,特别是static代码块,在这里我们可以做大量的工作,比如注册自己,初始化环境等,这才是要重点关注的逻辑.

    例如下代码:

     1 public class Client {
     2     public static void main(String[] args) throws Exception{
     3         //动态加载
     4         Class.forName("cn.summerchill.test.Utils");        
     5     }
     6 }
     7 
     8 class Utils{
     9     //静态代码块
    10     static{
    11         System.out.println("Do Something");
    12     }
    13     //静态方法
    14     public static void doStuff(){}
    15 }

    在Client类中,我们并没有对Utils做任何初始化,只是通过forName方法加载了Utils类,但是却能产生了一个"Do Something"的输出,这就是Utils类被加载之后,JVM会自动初始化其static变量和static代码块,这就是类加载机制所决定的.

    对于此种动态加载,最经典的就是数据库驱动程序中的加载片段.代码如下:

    //加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    String url="jdbc:mysql://localhost:3306/db?user=admin&password=admin";
    Connection conn = DriverManager.getConnection(url);
    Statement stmt = conn.createStatement();
    ..........................

    在没有Hibernate和Ibatis,MyBatis等ORM框架的情况下,基本上每个系统都会有这么一个JDBC的连接类,然后提供诸如Query,Delete等的方法.

    加上Class.forName("com.mysql.jdbc.Driver")没有任何的输出却非常的有用.

     1 public class Driver extends NonRegisteringDriver implements java.sql.Driver {
     2     static {
     3         try {
     4             java.sql.DriverManager.registerDriver(new Driver());
     5         } catch (SQLException E) {
     6             throw new RuntimeException("Can't register driver!");
     7         }
     8     }
     9 
    10     public Driver() throws SQLException {
    11     }
    12 }

    该程序的逻辑是:数据库的驱动程序已经由NonRegisteringDriver实现了,Driver类只是负责把自己注册到DriverManager中.

    当程序动态加载驱动时,也就是执行到Class.forName("****")时,Driver类会被加载到内存中,于是static代码块开始执行,也就是把自己注册到DriverManager中.

    需要说明的是,forName只是把一个类加载到内存中,并不保证由此产生一个实例对象,也不会执行任何方法,之所以会初始化static代码,那是由类加载机制所决定的.

    而不是由forName决定的,也就是说,如果没有static属性或者static代码块,forName就只是加载类,没有任何执行行为.

    forName只是加载类,并不执行任何代码.

  • 相关阅读:
    python 爬取豆瓣电影短评并wordcloud生成词云图
    基于javaweb人脸识别注册登录系统
    html/jsp导出pdf格式的几种方法(jsPDF,iText,wkhtmltopdf)
    微信小程序wx.getLocation()获取经纬度及JavaScript SDK调用腾讯地图API获取某一类地址
    微信小程序登录流程及解析用户openid session_key,获取用户信息
    Windows Server 2012 R2服务器部署Tomcat JDK、安装Mysql以及将Java项目部署到CVM
    Tomcat出现端口占用错误
    linux cmake error undefined reference to symbol 'pthread_create@@GLIBC_2.2.5
    CMake Warning This command specifies the relative path as a link directory.
    linux vim查看文件编码格式
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5626166.html
Copyright © 2011-2022 走看看