http://www.360doc.com/content/10/0712/10/1720440_38421273.shtml#

使用jdbc方式连接数据库时会使用一句代码Class.forName(String className).这句话是什么意思呢?首先说一点Class.forName(String className)这个方法的作用是装载className这个字符串指定的类。

官方文档

 

返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

Class.forName(className, true, currentLoader)

其中 currentLoader 表示此类的定义类加载器。

例如,以下代码片段返回 java.lang.Thread 类的运行时 Class 描述符。

Class t = Class.forName("java.lang.Thread")

调用 forName("X") 将导致名为 X 的类被初始化。

参数:

className - 所需类的完全限定名。

返回:

具有指定名的类的 Class 对象。

通俗的说就是:获得字符串参数中指定的类,并初始化该类

类装载

 

类装载就是把一个类或是一个接口的字节码文件,通过解析该字节码来构建代表这个类或是这个接口的实例的过程。 这个字节码文件来源可能是压缩包、网络、运行时编译出的或者自动生成的class文件,jvm spec没有规定必须从什么地方加载。

类装载的两种方式:

1.Class c1 = Class.forName ("java.lang.String");

 

2.ClassLoader cl = new  ClassLoader();

Class cl.loadClass( String name, boolean resolve );

两种装载方法的区别:

 

不同的类装载器

 

Class.forName是从指定的classloader中装载类,如果没有指定,也就是一个参数的时候,是从装载当前对象实例所在的classloader中装载类。

而ClassLoader的实例调用loadclass方法,是指从当前ClassLoader实例中调用类,而这个实例与装载当前所在类实例的Classloader也许不是同一个.

说白了就是他们实现装载的时候,使用的类装载器的指定是不同的。那为什么使用不同的ClassLoader来装载类呢?

其实使用多个classloader加载类的情况非常常见,比如说我们的app server都是这样的. 在Web与EJB间, 他们的classLoader就是不同的,这样做的目的就是为了避免两者间类装载的相互干扰。

是否实例化类

 

Class的装载分了三个阶段,loading(装载),linking(连接)和initializing(实例化)分别定义在The Java Language Specification的12.2,12.3和12.4。

Class.forName(className)实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。注意第二个参数,是指Class被loading后是不是必须被初始化。

ClassLoader.loadClass(className)实际上调用的是ClassLoader.loadClass(name, false),第二个参数指出Class是否被link。

区别就出来了。Class.forName(className)装载的class已经被实例化,而ClassLoader.loadClass(className)装载的class还没有被link,所以就更谈不上实例化了。

一般情况下,这两个方法效果一样,都能装载Class。但如果程序需要Class被实例化,就必须用Class.forName(name)了。

例如,在JDBC中加载mysql的驱动类时(关于注册jdbc驱动请参看另外一篇文章,jdbc注册驱动的三种方式),Class.forName("com.mysql.jdbc.Driver"),如果换成getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行,因为它只是向jvm装载了Driver并没有实例化,就不能执行响应的操作。

打开com.mysql.jdbc.Driver的源代码看看,

//

// Register ourselves with the DriverManager

//

static {

try {

java.sql.DriverManager.registerDriver(new Driver());

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

可以看到,Driver在static块中会注册自己到java.sql.DriverManager。而static块就是在Class的初始化中被执行。所以这个地方就只能用Class.forName(className)。

资源

 

最新文章

  1. 小议map排序问题
  2. oracle pctfree和pctused详解
  3. myeclipse高版本对应tomcat低版本解决办法
  4. Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name. 的解决方法
  5. 《C++ primer》--第9章
  6. nand烧写分析/内核在启动过程中式如何将这个文件映射成/目录及各子目录的?
  7. ELK菜鸟手记 (三) - X-Pack权限控制之给Kibana加上登录控制以及index_not_found_exception问题解决
  8. 全国省市县区域信息最新数据库脚本(mysql版本)
  9. 【Linux】【MySQL】CentOS7、MySQL8.0.13 骚操作速查笔记——专治各种忘词水土不服
  10. unittest中忽略某些测试用例的执行
  11. python3 对拉勾数据进行可视化分析
  12. [mvc] 过滤器filter一览
  13. NSLog无法使用
  14. PAT 甲级 1017 Queueing at Bank
  15. js中数组相关的Api
  16. 简易的命令行聊天室程序(Winsock,服务器&客户端)
  17. IT简历
  18. JVM插码之五:Java agent+ASM实战--监控所有方法执行时间
  19. 分别编写两个类Point2D,Point3D来表示二维空间和三维空间的点,使之满足下列要求:
  20. 6/8 sprint2 看板和燃尽图的更新

热门文章

  1. UVa11762 Race to 1
  2. 在Ubuntu / Ubuntu Kylin下安装和卸载 Nodepadqq
  3. 获取当前网络中的电脑数目及MAC-通过MAC查找IP-通过IP查询机器名
  4. LeetCode OJ--Remove Duplicates from Sorted Array
  5. 天梯赛 - L2-005 集合相似度
  6. 快速掌握分布式搜索引擎ElasticSearch(一)
  7. vue常用指命
  8. netty-类图对比
  9. sql标准支持了事务隔离级别
  10. Handler处理机制