Class.forName()用法详解

 

Class.forName()用法详解

标签: classjvmjdbc数据库documentationjava
 分类:
Java考古学(74) 
主要功能
Class.forName(xxx.xx.xx)返回的是一个类
Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,
也就是说JVM会执行该类的静态代码段

下面,通过解答以下三个问题的来详细讲解下Class.forName()的用法。
一.什么时候用Class.forName()?
先来个热身,给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?你第一想到的肯定是new,但是注意一点:
A a = (A)Class.forName(“pacage.A”).newInstance();
这和你 A a = new A(); 是一样的效果。

现在言归正传。
动态加载和创建Class 对象,比如想根据用户输入的字符串来创建对象时需要用到:
String str = “用户输入的字符串” ;
Class t = Class.forName(str);
t.newInstance();

在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。

Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。 例如:
class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();

其中ExampleInterface是Example的接口,可以写成如下形式:
String className = “Example”;
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();

进一步可以写成如下形式:
String className = readfromXMlConfig;//从xml 配置文件中获得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();

上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不变,甚至可以更换Example的兄弟类Example2 , Example3 , Example4……,只要他们继承ExampleInterface就可以。

从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:
1、这个类已经加载;
2、这个类已经连接了。
而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载Java API的那个加载器。

现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。

二.new 和Class.forName()有什么区别?
其实上面已经说到一些了,这里来做个总结:
首先,newInstance( )是一个方法,而new是一个关键字;
其次,Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用 new关键字生成对象没有这个限制。
简言之:
newInstance(): 弱类型,低效率,只能调用无参构造。
new: 强类型,相对高效,能调用任何public构造。
Class.forName(“”)返回的是类。
Class.forName(“”).newInstance()返回的是object 。
三.为什么在加载数据库驱动包的时候有用的是Class.forName( ),却没有调用newInstance( )?
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。
通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为了动态加载类。
通常编码过程中,在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此,单单使用Class.forName( )是动态加载类是没有用的,其最终目的是为了实例化对象。

有数据库开发经验朋友会发现,为什么在我们加载数据库驱动包的时候有的却没有调用newInstance( )方法呢?
即有的jdbc连接数据库的写法里是Class.forName(xxx.xx.xx);而有一 些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?
刚才提到,Class.forName(“”);的作用是要求JVM查找并加载指定的类,首先要明白,java里面任何class都要装载在虚拟机上才能运行,而静态代码是和class绑定的,class装载成功就表示执行了你的静态代码了,而且以后不会再走这段静态代码了。
而我们前面也说了,Class.forName(xxx.xx.xx)的作用就是要求JVM查找并加载指定的类,如果在类中有静态初始化器的话,JVM必然会执行该类的静态代码段。
而在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC Driver的 Driver类的代码都必须类似如下:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}
既然在静态初始化器的中已经进行了注册,所以我们在使用JDBC时只需要Class.forName(XXX.XXX);就可以了。

相关英文参考文献如下:
we just want to load the driver to jvm only, but not need to user the instance of driver,
so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(),
the result will same as calling Class.forName(xxx.xx.xx),
because Class.forName(xxx.xx.xx).newInstance() will load driver first,
and then create instance, but the instacne you will never use in usual,
so you need not to create it.

转载于:https://www.cnblogs.com/w-wfy/p/6010250.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[poco] 访问数据库

From: https://blog.csdn.net/hl2015222050145/article/details/52335422?utm_sourceblogxgwz6 poco访问数据基本步骤: a. 创建会话(session) b. 从DB中读写数据 c. 使用statements d. 使用容器(Collection) (数据,集合...) …

应对不良网络文化的技术之一——网络信息抽取技术

1 引言 2008年1月17日,中国互联网络信息中心(CNNIC)发布了《第21次中国互联网络发展状况统计报告》[1],报告显示: (1) 截至2007年12月,网民数已增至2.1亿人。中国网民数增长迅速,比2007年6月增加4800万人&…

最安全的js类型检测

众所周知js内置的类型检测机制不可靠,比如typeof操作符,对于正则和数组检测时返回值都是object, 而使用instanceof检测类型时,虽然可以对正则和数组正常验证,但验证undefined会报错,还有对于Symbol无法验证…

HBuilder完成webApp入门(2)

一、HBuilder的下载地址:http://www.dcloud.io/,点击那个“DownLoad”就可以 了 二、假设一切顺利,启动HBuilder后,大家会看到如下的界面 点击新建移动APP: 接下来就会弹出一个选择模板的对话框: 默认的模板…

js防篡改对象之不可扩展对象

const person {name: 啦啦德玛西亚}console.log(Object.isExtensible(person))//true//使用Object.preventExtensions()可以将对象修改为不可扩展对象,无法再给对象添加属性和方法Object.preventExtensions(person)//使用Object.isExtensible()方法可以确定对象是否…

高可用集群 heartbeatv1实例

——————— 高可用集群的简单配置 ————————地址规划 主节点:HA1 172.16.21.13 hostname node2.magedu.com备节点: HA2 172.16.21.14 hostname node1.magedu.comVIP 172.16.21.9前提工作1,配置主机名 hostname保证uname …

你知道“拉黑”、“关注”、“点赞”、“转发”、“分享到朋友圈”等英语咋说吗?

From: https://www.sohu.com/a/220161051_559507 “分享到朋友圈”等英语咋说吗? Mini apps 小程序 小程序”(mini apps)是一个不需要下载安装就可使用的应用(apps that can be accessed without downloading)&#x…

C#进化史

C#进化史 C#进化史从数据类型看C#演化C# 1写的产品类C# 强类型集合——解决限制1和2c# 自动属性——解决限制3c# 4 命名实参C# 1~C# 4的演变历程排序C# 1——提供一个IComparer实现C# 2——泛型比较器C# 3——Lambda表达式、扩展方法C# 1~C# 3简化排序的历程查询集合C# 1——循…

防篡改对象之密封对象

const person {name: 啦啦德玛西亚}console.log(Object.isExtensible(person))// trueconsole.log(Object.isSealed(person))// false// 使用Object.seal()将对象修改为密封对象// 密封对象不可扩展,而且已有成员的[[Configurable]]特性将被设置为false// 意味着不…

配套自测连载(三)

接上期(答案已给出)本期是专门针对《深入理解计算机网络》图书第4章而编写的10道计算机网络体系架构中的物理层技术自测题,可以检验你对本章的学习效果。把你的答案直接写在评论中即可,笔者将在每期发表10天后给出正确答案。本书是国内最通俗、最系统的计…

[json] JSON for Modern C++

有幸能接触到这个,这是我遇到的使用最方便的json了,效率没研究过! 简单了使用了下,感觉非常好用,记录下: 要使用这个json,只需要使用json.hpp就行,放入自己的工程里,但…

面向对象的需求分析方法

面向对象的需求分析方法 面向对象的需求分析方法的核心是利用面向对象的概念和方法为软件需求建造模型。它包含面向对象风格的图形语言机制和用于指导需求分析的面向对象方法学。 面向对象的思想最初起源于 20世纪 60年代中期的仿真程序设计语言Simula67。20世纪80年代初出现的…

js防篡改对象之冻结对象

const person {name: 啦啦德玛西亚,_job: 无业}Object.defineProperty(person, job, {get: function() {return this._job},set: function(newValue) {this._job newValue}})console.log(Object.isFrozen(person))// false//使用Object.freeze()将对象修改为冻结对象&#xf…

libinject的编译

libinject是一个Android进程注入实例,其下载地址为:http://download.csdn.net/download/ljhzbljhzb/3680780 libinject的编译需要NDK开发环境,在NDK安装成功之后,可以先将其自带的实例中的HelloJni导入到eclipse中,编译…

Boost - 序列化 (Serialization)

From: https://blog.csdn.net/zj510/article/details/8105408 程序开发中,序列化是经常需要用到的。像一些相对高级语言,比如JAVA, C#都已经很好的支持了序列化,那么C呢?当然一个比较好的选择就是用Boost,这个号称C准…

Linux Supervisor 守护进程基本配置

supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控、管理进程。常用于管理与某个用户或项目相关的进程。 组成部分supervisord:服务守护进程supervisorctl:命令行客户端Web Server:提供与supervisorctl功能相当的WEB操…

ES6使用object的is()方法比较两个值

此前js比较两个值是否相等时,一般使用 或 符号,我之前倾向使用后者,因为可以避免比较时触发强制类型转换,但某些情况使用 依然有问题,比如再比较NaN NaN时,返回的是false,需要使用isNaN()才能…

关闭子窗口 父窗口自动刷新

function clsoseForm(){window.opener.location.hrefwindow.opener.location.href; window.opener.location.reload();window.close();}转载于:https://blog.51cto.com/congwa/1199250

使用vue的sync修饰符进行子父组件的数据绑定

官方文档 父组件代码 <template><div><input type"button" value"我是父组件的按钮" click"show" /><!-- 在需要子组件修改的数据后加上.sync即可 --><child :isShow.syncisShow v-show"isShow" />&l…

三阶魔方还原公式

From: https://www.cnblogs.com/zqifa/p/mofang-1.html 1. 第二层棱块归位&#xff1a; 2. 顶层十字 3. 顶层棱中间块归位 这一步的目的是使顶层的4个棱中间块全部归位。 转动顶层(U)&#xff0c;若可以使一个棱中间块归位(如下图左&#xff0c;这里以[红-黄]块为例)&#x…