全新旗舰版上线 引领行业未来

选择您想了解的产品

微单旗舰版

马上了解

微单标准版

马上了解

百利APP版

马上了解

安装教程

马上了解

java反射(java反射机制原理详解)

来源:小凤 发布时间:2021-04-14 15:23

  JAVA反射机制是在运行状况中,关于恣意一个类,都能够知道这个类的一切特点和办法;关于恣意一个目标,都能够调用它的恣意一个办法和特点;这种动态获取的信息以及动态调用目标的办法的功用称为java言语的反射机制。

  要想解剖一个类,有必要先要获取到该类的字节码文件目标。而解剖运用的便是Class类中的办法.所以先要获取到每一个字节码文件对应的Class类型的目标.

  以上的总结便是什么是反射

  反射便是把java类中的各种成分映射成一个个的Java目标

  例如:一个类有:成员变量、办法、结构办法、包等等信息,运用反射技能能够对一个类进行解剖,把个个组成部分映射成一个个目标。(其实:一个类中这些成员办法、结构办法、在加入类中都有一个类来描述)

  如图是类的正常加载进程:反射的原理在与class目标。

  了解一下加载的时分:Class目标的由来是将class文件读入内存,并为之创建一个Class目标。java

  二、Java中为什么需求反射?反射要解决什么问题?

  Java中编译类型有两种:

  静态编译:在编译时确认类型,绑定目标即经过。

  动态编译:运行时确认类型,绑定目标。动态编译最大极限地发挥了Java的灵活性,表现了多态的应用,能够减低类之间的耦合性。

  Java反射是Java被视为动态(或准动态)言语的一个关键性质。这个机制答应程序在运行时透过ReflectionAPIs取得任何一个已知称号的class的内部信息,包含其modifiers(诸如public、static等)、superclass(例如Object)、完成之interfaces(例如Cloneable),也包含fields和methods的一切信息,并可于运行时改动fields内容或唤起methods。

  Reflection能够在运行时加载、探知、运用编译期间完全未知的classes。即Java程序能够加载一个运行时才得知称号的class,获取其完好结构,并生成其目标实体、或对其fields设值、或唤起其methods。

  反射(reflection)答应静态言语在运行时(runtime)检查、修改程序的结构与行为。

  在静态言语中,运用一个变量时,有必要知道它的类型。在Java中,变量的类型信息在编译时都保存到了class文件中,这样在运行时才干确保准确无误;换句话说,程序在运行时的行为都是固定的。假如想在运行时改动,就需求反射这东西了。

  完成Java反射机制的类都坐落java.lang.reflect包中:

  Class类:代表一个类

  Field类:代表类的成员变量(类的特点)

  Method类:代表类的办法

  Constructor类:代表类的结构办法

  Array类:提供了动态创建数组,以及拜访数组的元素的静态办法

  一句话归纳便是运用反射能够赋予jvm动态编译的能力,否则类的元数据信息只能用静态编译的方法完成,例如热加载,Tomcat的classloader等等都无法支撑。java反射目标办法

  Java反射机制定义

  Java反射机制是在运行状况中,关于恣意一个类,都能够知道这个类中的一切特点和办法;关于恣意一个目标,都能够调用它的恣意一个办法和特点;这种动态获取的信息以及动态调用目标的办法的功用称为java言语的反射机制。

  Java反射机制的功用

  1.在运行时判别恣意一个目标所属的类。

  2.在运行时结构恣意一个类的目标。

  3.在运行时判别恣意一个类所具有的成员变量和办法。

  4.在运行时调用恣意一个目标的办法。

  5.生成动态署理。

  Java反射机制的运用场景

  1.逆向代码,例如反编译

  2.与注解相结合的结构例如Retrofit

  3.单纯的反射机制运用结构例如EventBus

  4.动态生成类结构例如Gson

  二、经过Java反射查看类信息

  取得Class目标

  每个类被加载之后,体系就会为该类生成一个对应的Class目标。经过该Class目标就能够拜访到JVM中的这个类。

  在Java程序中取得Class目标通常有如下三种办法:

  1.运用Class类的forName(StringclazzName)静态办法。该办法需求传入字符串参数,该字符串参数的值是某个类的全限定名(必须增加完整包名)。

  2.调用某个类的class特点来获取该类对应的Class目标。

  3.调用某个目标的getClass()办法。该办法是java.lang.Object类中的一个办法。

  //第一种办法经过Class类的静态办法——forName()来完成class1=Class.forName(“com.lvr.reflection.Person”);//第二种办法经过类的class特点class1=Person.class;//第三种办法经过目标getClass办法Personperson=newPerson();Classclass1=person.getClass();

  获取class目标的特点、办法、结构函数等

  1.获取class目标的成员变量

  Field[]allFields=class1.getDeclaredFields();//获取class目标的一切特点Field[]publicFields=class1.getFields();//获取class目标的public特点FieldageField=class1.getDeclaredField(“age”);//获取class指定特点FielddesField=class1.getField(“des”);//获取class指定的public特点

  2.获取class目标的办法

  Method[]methods=class1.getDeclaredMethods();//获取class目标的一切声明办法Method[]allMethods=class1.getMethods();//获取class目标的一切public办法包括父类的办法Methodmethod=class1.getMethod(“info”,String.class);//返回次Class目标对应类的、带指定形参列表的public办法MethoddeclaredMethod=class1.getDeclaredMethod(“info”,String.class);//返回次Class目标对应类的、带指定形参列表的办法

  3.获取class目标的结构函数

  Constructor[]allConstructors=class1.getDeclaredConstructors();//获取class目标的一切声明结构函数Constructor[]publicConstructors=class1.getConstructors();//获取class目标public结构函数Constructorconstructor=class1.getDeclaredConstructor(String.class);//获取指定声明结构函数ConstructorpublicConstructor=class1.getConstructor(String.class);//获取指定声明的public结构函数

  4.其他办法

  Annotation[]annotations=(Annotation[])class1.getAnnotations();//获取class目标的一切注解Annotationannotation=(Annotation)class1.getAnnotation(Deprecated.class);//获取class目标指定注解TypegenericSuperclass=class1.getGenericSuperclass();//获取class目标的直接超类的TypeType[]interfaceTypes=class1.getGenericInterfaces();//获取class目标的一切接口的type调集

  获取class目标的信息

  比较多。

  booleanisPrimitive=class1.isPrimitive();//判别是否是根底类型booleanisArray=class1.isArray();//判别是否是调集类booleanisAnnotation=class1.isAnnotation();//判别是否是注解类booleanisInterface=class1.isInterface();//判别是否是接口类booleanisEnum=class1.isEnum();//判别是否是枚举类booleanisAnonymousClass=class1.isAnonymousClass();//判别是否是匿名内部类booleanisAnnotationPresent=class1.isAnnotationPresent(Deprecated.class);//判别是否被某个注解类润饰StringclassName=class1.getName();//获取class姓名包含包名途径PackageaPackage=class1.getPackage();//获取class的包信息StringsimpleName=class1.getSimpleName();//获取class类名intmodifiers=class1.getModifiers();//获取class拜访权限Class[]declaredClasses=class1.getDeclaredClasses();//内部类ClassdeclaringClass=class1.getDeclaringClass();//外部类

  三、经过Java反射生成并操作目标

  生成类的实例目标

  1.运用Class目标的newInstance()办法来创立该Class目标对应类的实例。这种办法要求该Class目标的对应类有默许结构器,而执行newInstance()办法时实际上是利用默许结构器来创立该类的实例。

  2.先运用Class目标获取指定的Constructor目标,再调用Constructor目标的newInstance()办法来创立该Class目标对应类的实例。经过这种办法能够选择运用指定的结构器来创立实例。

  //第一种办法Class目标调用newInstance()办法生成Objectobj=class1.newInstance();//第二种办法目标取得对应的Constructor目标,再经过该Constructor目标的newInstance()办法生成Constructorconstructor=class1.getDeclaredConstructor(String.class);//获取指定声明结构函数obj=constructor.newInstance(“hello”);

  调用类的办法

  1.经过Class目标的getMethods()办法或者getMethod()办法取得指定办法,返回Method数组或目标。

  2.调用Method目标中的Objectinvoke(Objectobj,Object…args)办法。第一个参数对应调用该办法的实例目标,第二个参数对应该办法的参数。

  //生成新的目标:用newInstance()办法Objectobj=class1.newInstance();//首要需求取得与该办法对应的Method目标Methodmethod=class1.getDeclaredMethod(“setAge”,int.class);//调用指定的函数并传递参数method.invoke(obj,28);

  当经过Method的invoke()办法来调用对应的办法时,Java会要求程序必须有调用该办法的权限。假如程序的确需求调用某个目标的private办法,则能够先调用Method目标的如下办法。

  setAccessible(booleanflag):将Method目标的acessible设置为指定的布尔值。值为true,指示该Method在运用时应该取消Java言语的拜访权限查看;值为false,则知识该Method在运用时要施行Java言语的拜访权限查看。

  拜访成员变量值

  1.经过Class目标的getFields()办法或者getField()办法取得指定办法获取,返回Field数组或目标。

  2.Field供给了两组办法来读取或设置成员变量的值:

  getXXX(Objectobj):获取obj目标的该成员变量的值。此处的XXX对应8种基本类型。假如该成员变量的类型是引证类型,则取消get后面的XXX。

  setXXX(Objectobj,XXXval):将obj目标的该成员变量设置成val值。

  //生成新的目标:用newInstance()办法Objectobj=class1.newInstance();//获取age成员变量Fieldfield=class1.getField(“age”);//将obj目标的age的值设置为10field.setInt(obj,10);//获取obj目标的age的值field.getInt(obj);

  还有很多其他操作,就不一一介绍了。

Telegram
771200
Letstalk
t770034939
返回顶部

返回顶部