第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > java 反射机制_基础篇:深入解析JAVA反射机制

java 反射机制_基础篇:深入解析JAVA反射机制

时间:2024-04-28 04:32:44

相关推荐

java 反射机制_基础篇:深入解析JAVA反射机制

反射的概念

java 的放射机制:在程序运行时,程序有能力获取一个类的所有方法和属性;并且对于任意一个对象,可以调用它的任意方法或者获取其属性

通俗解析:java 文件需要编译成. class 文件才能被 jvm 加载使用, 对象的. class 数据在 jvm 里就是 Class;我们如果能拿到这个 Class对象,就能获取该 Class对应的对象类型,及在该类型声明的方法和属性值;还可以根据 Class创建相应的类型对象,通过 Field,Method 反过来操作对象

java 相关类介绍

获取 Class 的三种方法

1 通过已知的类型获取 class

//根据Example获取Class=》Example.class

publicClassgetExample(){

Classclazz=Example.class;returnclazz;

}

2 通过实例对象获取 class

publicClassgetExampleByInstance(){

Exampleexample=newExample();

// getClass是Object类里面的方法;《?》是通配符

Classclazz=example.getClass();return(Class)clazz;

}

3 通过 Class.forName 获取全路径指定类名的 class

/\*\*forName0本地方法,C++实现,jvm调用

\* 1 className 是个类名 2 initialize 是否延迟加载 3 loader 加载器

\*/

privatestaticnativeClassforName0(StringclassName,booleaninitialize,

ClassLoaderloader,Classcaller)throwsClassNotFoundException;

publicstaticClassforName(StringclassName)throwsClassNotFoundException{

Classcaller=Reflection.getCallerClass();

returnforName0(className,true,ClassLoader.getClassLoader(caller),caller);

}

//两个forName方法最终都会调用forName0方法去加载class

publicstaticClassforName(Stringname,

booleaninitialize,ClassLoaderloader)throwsClassNotFoundException{

....

returnforName0(name,initialize,loader,caller);

}

//示例:通过java.lang.Integer

publicClassgetInteger()throwsClassNotFoundException{

Classclazz=Class.forName("java.lang.Integer");return(Class)clazz;

}

JAVA 反射 API

Class 常用操作方法

//获取所有的构造方法/privatepublic

publicConstructor\[\]getDeclaredConstructors()

//获取特定的构造方法/privatepublic

publicConstructorgetDeclaredConstructor(Class...parameterTypes)

//获取类的父类

publicnativeClassgetSuperclass()

//获取类实现的接口

privateClass\[\]getInterfaces(booleancloneArray)

//获取在类内定义的内部类或接口

publicClass\[\]getDeclaredClasses()

//获取所有的方法

publicMethod\[\]getDeclaredMethods()throwsSecurityException

//根据方法名和参数获得特定的方法

publicMethodgetDeclaredMethod(Stringname,Class...parameterTypes)

//获取类型的定义的所有属性

publicField\[\]getFields()throwsSecurityException

//根据属性命名获得特定的Field

publicFieldgetField(Stringname)

Method 常用的操作方法

//获得方法的放回类型

publicClassgetReturnType()

//获得方法的传入参数类型

publicClass\[\]getParameterTypes()

//obj是实例对象,args是方法,反过来由Method控制对象的方法调用

publicObjectinvoke(Objectobj,Object...args)

Field 常用的操作方法

//属性与obj相等则返回true

publicbooleanequals(Objectobj)

//获得obj中对应的属性值

publicObjectget(Objectobj)

//设置obj中对应属性值

publicvoidset(Objectobj,Objectvalue)

Constructor

//根据传递的参数创建类的对象:initargs构造方法参数

publicTnewInstance(Object...initargs)

1 根据 class 创建对象

//方式一clazz.newInstance()

Classclazz=Example.class;

Exampleexample=clazz.newInstance();

//方式二先获取再由Constructor:clazz.getConstructors()/getConstructor(...)

//再由Constructor.newInstance方法构造对象

-----------------------------------------

publicclassExample{

privateintvalue;

publicExample(){}//如果只声明有参构造函数,clazz.newInstance()会报错

publicExample(Integervalue){this.value=value;}

staticpublicvoidmain(String\[\]args)throwsException{

Classclazz=Example.class;

//根据指定构造函数参数获取Constructor

Constructorconstructor=clazz.getConstructor(Integer.class);

Exampleexample=constructor.newInstance(100);

System.out.println(example.value);

}

}

2 由 class 获取 Field,并操作实例的属性

publicclassExample{

privateintvalue,count;

staticpublicvoidmain(String\[\]args)throwsException{

Classclazz=Example.class;

//获取所有的属性,getField只能获取public的属性

Field\[\]fs=clazz.getDeclaredFields();

//根据名称获取指定Field

Fieldvalue=clazz.getDeclaredField("value");

Exampleexample=clazz.newInstance();

//使用反射机制可以打破封装性,导致了java对象的属性不安全

value.setAccessible(true);//setAccessible(true)让private的参数可赋值操作

//由Field反过去设置example的值

value.set(example,100);

System.out.println(example.value);

}

}

3 由 class 获取 Method,并反射调用实例方法

publicclassExample{

publicstaticvoidmain(String\[\]args)throwsException{

Classclazz=Example.class;

Exampleexample=clazz.newInstance();

Method\[\]methods=clazz.getDeclaredMethods();

//getDeclaredMethod和getMethod是:getMethod只能返回public的方法

Methodmethod=clazz.getDeclaredMethod("hello",String.class);

method.setAccessible(true);

method.invoke(example,"cscw");

}

privatevoidhello(Stringname){System.out.println(name+"Hello!");}

}

-----

cscwHello!

反射机制应用的场景

1 动态拓展:假设有同一组类是实现相同的接口,并且类的加载方式不限制。当我们需要那种具体类实现的功能时,只需加载. class 文件,并获取对应的 Class对象。可以由 Class 或者 Constructor 实例化对象 instance;根据接口定义,可以获取 Class里的某一方法 Method,并配合 instance 反射调用功能方法

2 Spring 的 IOC 就是基于反射机制实现

3 JDK 的动态代理

反射和 JDK 动态代理

在 Java 的 java.lang.reflect 包下提供了一个 Proxy 类和一个 InvocationHandler 接口。通过这个类和接口可以生成 JDK 动态代理类或动态代理对象

publicinterfaceInvocationHandler{

//所有方法都会调用此代理方法

Objectinvoke(Objectvar1,Methodvar2,Object\[\]var3)throwsThrowable;

}

publicclassProxyimplementsSerializable{

...

//根据interfaces和InvocationHandler生成代理对象

publicstaticObjectnewProxyInstance(ClassLoaderloader,

Class\[\]interfaces,InvocationHandlerh)

...

JDK 的动态代理由 Proxy 和 InvocationHandler 实现;而被代理对象必须实现一个接口。代理对象由 Proxy 生成,可转为接口 interface 的实现类对象 OBJ。当调用 OBJ 的方法时,则会触发 InvocationHandler.invoke,参数依次为「代理对象」「Method 对象」, 和「方法 Method 所需的参数」。在 invoke 方法可以加入拓展的逻辑,如日志记录操作;「并可以在 invoke 里利用反射的技术调用被代理对象方法」

示例

publicclassExampleFactoryimplementsInvocationHandler{

privateTtarget;//被代理对象

publicTbind(Tobj){

target=obj;return(T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),

obj.getClass().getInterfaces(),this);

}

/\*\*Objecto是代理对象;o的方法调用->ExampleFactory.invoke

\*invoke(...)->在invoke方法里面反射调用代理对象方法+增强逻辑

\*/

@Override

publicObjectinvoke(Objecto,Methodmethod,Object\[\]objects)throwsThrowable{

//增强逻辑

System.out.println("logstart");

//反射调用被代理对象方法

Objectresult=method.invoke(target,objects);

System.out.println("logend");returnresult;

}

}

-----------

publicinterfaceFace{

voidhello(Stringname);

}

---------

//被代理对象必须实现一个接口,并由接口方法对方提供功能

publicclassExampleimplementsFace{

publicvoidhello(Stringname){

System.out.println(name+"Hello!");

}

publicstaticvoidmain(String\[\]args){

//ExampleFactory相当于一个中介人

ExampleFactoryfactory=newExampleFactory<>();

//example是代理对象

Faceexample=exampleProxy.bind(newExample());

example.hello("思婷");

}

}

-----logstart

思婷Hello!logend

欢迎指正文中错误

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。