播放记录

Class.forName() 映射 用法详解

博客JSP 2019年08月31日 01:25:13

1、Class 类简介:


Java 程序在运行时,Java 运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是 Class 类。Class 类封装一个对象和接口运行时的状态,当装载类时,Class 类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个 Class 对象。
虚拟机为每种类型管理一个独一无二的 Class 对象。也就是说,每个类(型)都有一个 Class 对象。运行程序时,Java 虚拟机(JVM)首先检查是否所要加载的类对应的 Class 对象是否已经加载。如果没有加载,JVM 就会根据类名查找.class 文件,并将其 Class 对象载入。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
一般某个类的 Class 对象被载入内存,它就用来创建这个类的所有对象。

一、如何得到 Class 的对象呢?有三种方法可以的获取:

1、调用 Object 类的 getClass()方法来得到 Class 对象,这也是最常见的产生 Class 对象的方法。例如:
MyObject x;
Class c1 = x.getClass();

2、使用 Class 类的中静态 forName()方法获得与字符串对应的 Class 对象。例如:
Class c2=Class.forName(“MyObject”),Employee 必须是接口或者类的名字。

3、获取 Class 类型对象的第三个方法非常简单。如果 T 是一个 Java 类型,那么 T.class 就代表了匹配的类对象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
注意:Class 对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的 int.class 是一个 Class 类型的对象。由于历史原因,数组类型的 getName 方法会返回奇怪的名字。

二、Class 类的常用方法

1、getName()

一个 Class 对象描述了一个特定类的属性,Class 类中最常用的方法 getName 以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

2、newInstance()

Class 还有一个有用的方法可以为类创建一个实例,这个方法叫做 newInstance()。例如:
x.getClass.newInstance(),创建了一个同 x 一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。

3、getClassLoader()

返回该类的类加载器。

4、getComponentType()
返回表示数组组件类型的 Class。

5、getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。

6、isArray()
判定此 Class 对象是否表示一个数组类。

三、Class 的一些使用技巧

1、forName 和 newInstance 结合起来使用,可以根据存储在字符串中的类名创建对象。例如
Object obj = Class.forName(s).newInstance();

2、虚拟机为每种类型管理一个独一无二的 Class 对象。因此可以使用==操作符来比较类对象。例如:
if(e.getClass() == Employee.class)…

2、 Class.forName()方法:


Class.forName:返回与给定的字符串名称相关联接口的 Class 对象。

Class.forName是一个静态方法,同样可以用来加载类。该方法有两种形式:Class.forName(String name, boolean initialize, ClassLoader loader)和 Class.forName(String className)。第一种形式的参数 name 表示的是类的全名;initialize 表示是否初始化类;loader 表示加载时使用的类加载器。第二种形式则相当于设置了参数 initialize 的值为 true,loader 的值为当前类的类加载器。

static Class

forName(String className)

Returns the Class object associated with the class or interface with the given string name.

static Class forName(String name,
boolean initialize,
 ClassLoader loader)Returns the Class object associated with the class or interface with the given string name, using the given class loader.

说明:

publicstatic Class forName(String className)

Returns the Class object associated withthe class or interface with the given string name. Invokingthis method is equivalent to:

Class.forName(className,true, currentLoader)

where currentLoader denotes the definingclass loader of the current class.

For example, thefollowing code fragment returns the runtime Class descriptor for theclass named java.lang.Thread:

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

A call to forName("X") causes theclass named X to beinitialized.

Parameters:

className – the fully qualifiedname of the desired class.

Returns:

the Class object for the classwith the specified name.

从官方给出的 API 文档中可以看出:

Class.forName(className)实际上是调用 Class.forName(className,true, this.getClass().getClassLoader())。第二个参数,是指 Class 被 loading 后是不是必须被初始化。可以看出,使用 Class.forName(className)加载类时则已初始化。

所以 Class.forName(className)可以简单的理解为:获得字符串参数中指定的类,并初始化该类。

 

一.首先你要明白在 java 里面任何 class 都要装载在虚拟机上才能运行。

1.      forName 这句话就是装载类用的(new 是根据加载到内存中的类创建一个实例,要分清楚)。

2.      至于什么时候用,可以考虑一下这个问题,给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?

A a = (A)Class.forName(“pacage.A”).newInstance();这和 A a =new A();是一样的效果。

3.      jvm 在装载类时会执行类的静态代码段,要记住静态代码是和 class 绑定的,class 装载成功就表示执行了你的静态代码了,而且以后不会再执行这段静态代码了。

4.      Class.forName(xxx.xx.xx)的作用是要求 JVM 查找并加载指定的类,也就是说 JVM 会执行该类的静态代码段。

5.      动态加载和创建 Class 对象,比如想根据用户输入的字符串来创建对象

String str = 用户输入的字符串

Class t = Class.forName(str);

t.newInstance();

 二.在初始化一个类,生成一个实例的时候,newInstance()方法和 new 关键字除了一个是方法,一个是关键字外,最主要有什么区别?

1.它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。

2.那么为什么会有两种创建对象方式?

这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。
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 就可以。
3.从 JVM 的角度看,我们使用关键字 new 创建一个类的时候,这个类可以没有被加载。  但是使用 newInstance()方法的时候,

就必须保证:

1、这个类已经加载;

2、这个类已经连接了。

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

三.最后用最简单的描述来区分 new 关键字和 newInstance()方法的区别:

1. newInstance: 弱类型。低效率。只能调用无参构造。
2. new: 强类型。相对高效。能调用任何 public 构造。

3、应用情景:


情景一:加载数据库驱动的时候

Class.forName 的一个很常见的用法是在加载数据库驱动的时候。

如:

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

Connection con=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName==JSP","jph","jph");

为什么在我们加载数据库驱动包的时候有的却没有调用 newInstance( )方法呢?

即有的 jdbc 连接数据库的写法里是 Class.forName(xxx.xx.xx);而有一些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?

刚才提到,Class.forName(“”);的作用是要求 JVM 查找并加载指定的类,如果在类中有静态初始化器的话,JVM 必然会执行该类的静态代码段。

而在 JDBC 规范中明确要求这个 Driver 类必须向 DriverManager 注册自己,即任何一个 JDBCDriver 的 Driver 类的代码都必须类似如下:

public classMyJDBCDriver implements Driver {

static{

DriverManager.registerDriver(new MyJDBCDriver());

}

}

 

既然在静态初始化器的中已经进行了注册,所以我们在使用 JDBC 时只需要 Class.forName(XXX.XXX);就可以了。

情景二:使用 AIDL 与电话管理 Servic 进行通信

Method method =Class.forName("android.os.ServiceManager")

.getMethod("getService",String.class);

// 获取远程 TELEPHONY_SERVICE 的 IBinder 对象的代理

IBinder binder =(IBinder) method.invoke(null, new Object[] { TELEPHONY_SERVICE});

// 将 IBinder 对象的代理转换为 ITelephony 对象

ITelephonytelephony = ITelephony.Stub.asInterface(binder);

// 挂断电话

telephony.endCall();

 


转载:https://www.teenshare.club/class-forname-%e6%98%a0%e5%b0%84-%e7%94%a8%e6%b3%95%e8%af%a6%e8%a7%a3.html

© 2018 www.qingketang.net 鄂ICP备18027844号-1

武汉快勤科技有限公司 13554402156 武汉市东湖新技术开发区关山二路特一号国际企业中心6幢4层7号

微信登录

扫码关注,全站教程免费播放

发表评论 X

登录成功
开通VIP

订单金额:

支付金额:

支付方式: