Java 反射机制详解.docx

上传人:b****6 文档编号:5994583 上传时间:2023-01-02 格式:DOCX 页数:20 大小:23.74KB
下载 相关 举报
Java 反射机制详解.docx_第1页
第1页 / 共20页
Java 反射机制详解.docx_第2页
第2页 / 共20页
Java 反射机制详解.docx_第3页
第3页 / 共20页
Java 反射机制详解.docx_第4页
第4页 / 共20页
Java 反射机制详解.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

Java 反射机制详解.docx

《Java 反射机制详解.docx》由会员分享,可在线阅读,更多相关《Java 反射机制详解.docx(20页珍藏版)》请在冰豆网上搜索。

Java 反射机制详解.docx

Java反射机制详解

动态语言

动态语言,是指程序在运行时可以改变其结构:

新的函数可以被引进,已有的函数可以被删除等在结构上的变化。

比如众所周知的ECMAScript(JavaScript)便是一个动态语言。

除此之外如Ruby、Python等也都属于动态语言,而C、C++等语言则不属于动态语言。

(引自:

XX百科)

varexecString="alert(Math.floor(Math.random()*10));";

eval(execString);

Class反射机制

∙指的是可以于运行时加载,探知和使用编译期间完全未知的类.

∙程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已经加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用他的任意一个方法和属性;

∙加载完类之后,在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息,而且这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以被称之为:

反射。

InstancesoftheclassClassrepresentclassesandinterfacesinarunningJavaapplication.Anenumisakindofclassandanannotationisakindofinterface.EveryarrayalsobelongstoaclassthatisreflectedasaClassobjectthatissharedbyallarrayswiththesameelementtypeandnumberofdimensions(维度).TheprimitiveJavatypes(boolean,byte,char,short,int,long,float,anddouble),andthekeywordvoidarealsorepresentedasClassobjects.

∙每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,通过该Class对象就可以访问到JVM中的这个类.

Class对象的获取

∙对象的getClass()方法;

∙类的.class(最安全/性能最好)属性;

∙运用Class.forName(StringclassName)动态加载类,className需要是类的全限定名(最常用).

从Class中获取信息

Class类提供了大量的实例方法来获取该Class对象所对应的详细信息,Class类大致包含如下方法,其中每个方法都包含多个重载版本,因此我们只是做简单的介绍,详细请参考JDK文档

获取类内信息

获取内容

方法签名

构造器

ConstructorgetConstructor(Class

>...parameterTypes)

包含的方法

MethodgetMethod(Stringname,Class

>...parameterTypes)

包含的属性

FieldgetField(Stringname)

包含的Annotation

AgetAnnotation(ClassannotationClass)

内部类

Class

>[]getDeclaredClasses()

外部类

Class

>getDeclaringClass()

所实现的接口

Class

>[]getInterfaces()

修饰符

intgetModifiers()

所在包

PackagegetPackage()

类名

StringgetName()

简称

StringgetSimpleName()

一些判断类本身信息的方法

判断内容

方法签名

注解类型?

booleanisAnnotation()

使用了该Annotation修饰?

booleanisAnnotationPresent(Class

extendsAnnotation>annotationClass)

匿名类?

booleanisAnonymousClass()

数组?

booleanisArray()

枚举?

booleanisEnum()

原始类型?

booleanisPrimitive()

接口?

booleanisInterface()

obj是否是该Class的实例

booleanisInstance(Objectobj)

使用反射生成并操作对象:

MethodConstructorField这些类都实现了java.lang.reflect.Member接口,程序可以通过Method对象来执行相应的方法,通过Constructor对象来调用对应的构造器创建实例,通过Filed对象直接访问和修改对象的成员变量值.

创建对象

通过反射来生成对象的方式有两种:

∙使用Class对象的newInstance()方法来创建该Class对象对应类的实例(这种方式要求该Class对象的对应类有默认构造器).

∙先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例(通过这种方式可以选择指定的构造器来创建实例).

通过第一种方式来创建对象比较常见,像Spring这种框架都需要根据配置文件(如applicationContext.xml)信息来创建Java对象,从配置文件中读取的只是某个类的全限定名字符串,程序需要根据该字符串来创建对应的实例,就必须使用默认的构造器来反射对象.

下面我们就模拟Spring实现一个简单的对象池,该对象池会根据文件读取key-value对,然后创建这些对象,并放入Map中.

配置文件

{

"objects":

[

{

"id":

"id1",

"class":

"com.fq.domain.User"

},

{

"id":

"id2",

"class":

"com.fq.domain.Bean"

}

]

}

ObjectPool

/**

*Createdbyjifangon15/12/31.

*/

publicclassObjectPool{

privateMappool;

privateObjectPool(Mappool){

this.pool=pool;

}

privatestaticObjectgetInstance(StringclassName)throwsClassNotFoundException,IllegalAccessException,InstantiationException{

returnClass.forName(className).newInstance();

}

privatestaticJSONArraygetObjects(Stringconfig)throwsIOException{

Readerreader=newInputStreamReader(ClassLoader.getSystemResourceAsStream(config));

returnJSONObject.parseObject(CharStreams.toString(reader)).getJSONArray("objects");

}

//根据指定的JSON配置文件来初始化对象池

publicstaticObjectPoolinit(Stringconfig){

try{

JSONArrayobjects=getObjects(config);

ObjectPoolpool=newObjectPool(newHashMap());

if(objects!

=null&&objects.size()!

=0){

for(inti=0;i

JSONObjectobject=objects.getJSONObject(i);

if(object==null||object.size()==0){

continue;

}

Stringid=object.getString("id");

StringclassName=object.getString("class");

pool.putObject(id,getInstance(className));

}

}

returnpool;

}catch(IOException|ClassNotFoundException|InstantiationException|IllegalAccessExceptione){

thrownewRuntimeException(e);

}

}

publicObjectgetObject(Stringid){

returnpool.get(id);

}

publicvoidputObject(Stringid,Objectobject){

pool.put(id,object);

}

publicvoidclear(){

pool.clear();

}

}

Client

publicclassClient{

@Test

publicvoidclient(){

ObjectPoolpool=ObjectPool.init("config.json");

Useruser=(User)pool.getObject("id1");

System.out.println(user);

Beanbean=(Bean)pool.getObject("id2");

System.out.println(bean);

}

}

User

publicclassUser{

privateintid;

privateStringname;

privateStringpassword;

publicintgetId(){

returnid;

}

publicvoidsetId(Integerid){

this.id=id;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetPassword(){

returnpassword;

}

publicvoidsetPassword(Stringpassword){

this.password=password;

}

@Override

publicStringtoString(){

return"User{"+

"id="+id+

",name='"+name+'/''+

",password='"+password+'/''+

'}';

}

}

Bean

publicclassBean{

privateBooleanusefull;

privateBigDecimalrate;

privateStringname;

publicBooleangetUsefull(){

returnusefull;

}

publicvoidsetUsefull(Booleanusefull){

this.usefull=usefull;

}

publicBigDecimalgetRate(){

returnrate;

}

publicvoidsetRate(BigDecimalrate){

this.rate=rate;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

@Override

publicStringtoString(){

return"Bean{"+

"usefull="+usefull+

",rate="+rate+

",name='"+name+'/''+

'}';

}

}

注意:

需要在pom.xml中添加如下依赖:

com.alibaba

fastjson

1.2.7

com.google.guava

guava

18.0

调用方法

当获取到某个类对应的Class对象之后,就可以通过该Class对象的getMethod来获取一个Method数组或Method对象.每个Method对象对应一个方法,在获得Method对象之后,就可以通过调用invoke方法来调用该Method对象对应的方法.

@CallerSensitive

publicObjectinvoke(Objectobj,Object...args)

throwsIllegalAccessException,IllegalArgumentException,

InvocationTargetException

{

...

}

下面我们对上面的对象池加强:

可以看到Client获取到的对象的成员变量全都是默认值,既然我们已经使用了JSON这么优秀的工具,我们又学习了动态调用对象的方法,那么我们就通过配置文件来给对象设置值(在对象创建时),新的配置文件形式如下:

{

"objects":

[

{

"id":

"id1",

"class":

"com.fq.domain.User",

"fields":

[

{

"name":

"id",

"value":

101

},

{

"name":

"name",

"value":

"feiqing"

},

{

"name":

"password",

"value":

"ICy5YqxZB1uWSwcVLSNLcA=="

}

]

},

{

"id":

"id2",

"class":

"com.fq.domain.Bean",

"fields":

[

{

"name":

"usefull",

"value":

true

},

{

"name":

"rate",

"value":

3.14

},

{

"name":

"name",

"value":

"bean-name"

}

]

},

{

"id":

"id3",

"class":

"com.fq.domain.ComplexBean",

"fields":

[

{

"name":

"name",

"value":

"complex-bean-name"

},

{

"name":

"refBean",

"ref":

"id2"

}

]

}

]

}

其中fields代表该Bean所包含的属性, name为属性名称, value为属性值(属性类型为JSON支持的类型), ref代表引用一个对象(也就是属性类型为Object,但是一定要引用一个已经存在了的对象)

/**

*@authorjifang

*@since15/12/31下午4:

00

*/

publicclassObjectPool{

privateMappool;

privateObjectPool(Mappool){

this.pool=pool;

}

privatestaticJSONArraygetObjects(Stringconfig)throwsIOException{

Readerreader=newInputStreamReader(ClassLoader.getSystemResourceAsStream(config));

returnJSONObject.parseObject(CharStreams.toString(reader)).getJSONArray("objects");

}

privatestaticObjectgetInstance(StringclassName,JSONArrayfields)

throwsClassNotFoundException,NoSuchMethodException,

IllegalAccessException,InstantiationException,InvocationTargetException{

//配置的Class

Class

>clazz=Class.forName(className);

//目标Class的实例对象

ObjecttargetObject=clazz.newInstance();

if(fields!

=null&&fields.size()!

=0){

for(inti=0;i

JSONObjectfield=fields.getJSONObject(i);

//需要设置的成员变量名

StringfieldName=field.getString("name");

//需要设置的成员变量的值

ObjectfieldValue;

if(field.containsKey("value")){

fieldValue=field.get("value");

}elseif(field.containsKey("ref")){

StringrefBeanId=field.getString("ref");

fieldValue=OBJECTPOOL.getObject(refBeanId);

}else{

thrownewRuntimeException("neithervaluenorref");

}

StringsetterName="set"+

fieldName.substring(0,1).toUpperCase()+

fieldName.substring

(1);

//需要设置的成员变量的setter方法

MethodsetterMethod=clazz.getMethod(setterName,fieldValue.getClass());

//调用setter方法将值设置进去

setterMethod.invoke(targetObject,fieldValue);

}

}

returntargetObject;

}

privatestaticObjectPoolOBJECTPOOL;

//创建一个对象池的实例(保证是多线程安全的)

privatestaticvoidinitSingletonPool(){

if(OBJECTPOOL==null){

synchronized(ObjectPool.class){

if(OBJECTPOOL==null){

OBJECTPOOL=newObjectPool(newConcurrentHashMap());

}

}

}

}

//根据指定的JSON配置文件来初始化对象池

publicstaticObjectPoolinit(Stringconfig){

//初始化pool

initSingletonPool();

try{

JSONArrayobjects=getObjects(config);

for(inti=0;objects!

=null&&i

JSONObjectobject=objects.getJSONObject(i);

if(object==null||object.size()==0){

continue;

}

Stringid=object.getString("id");

StringclassName=object.getString("class");

//初始化bean并放入池中

OBJECTPOOL.putObject(id,getInstance(className,object.getJSONArray("fields")));

}

returnOBJECTPOOL;

}catch(IOException|ClassNotFoundException|

InstantiationException|IllegalAccessException|

NoSuchMethodException|InvocationTargetExceptione){

thrownewRuntimeException(e);

}

}

publicObjectgetObject(Stringid){

returnpool.get(id);

}

publicvoidputObject(Stringid,Objectobject){

pool.put(id,object);

}

p

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1