Java 反射简介

反射是指在运行时将类的属性、构造函数和方法等元素动态地映射成一个个对象。通过这些对象我们可以动态地生成对象实例,调用类的方法和更改类的属性值。

2. 使用场景

什么情况下运用JAVA反射呢?如果编译时根本无法预知对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,此时就必须使用反射。

使用反射可以实现下面的功能:

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时判断任意一个类所具有的方法和属性

在运行时调用任意一个对象的方法

生成动态代理

3. 获得Class对象的几种方式

前面已经介绍过了,每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类。在Java程序中获得Class对象通常有如下3种方式。

使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整包名)。

调用某个类的class属性来获取该类对应的Class对象。例如,Person.class将会返回Person类对应的Class对象。

调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法,所以所有的Java对象都可以调用该方法,该方法将会返回该对象所属类对应的Class对象。

对于第一种方式和第二种方式都是直接根据类来取得该类的Class对象,相比之下,第二种方式有如下两种优势。

代码更安全。程序在编译阶段就可以检查需要访问的Class对象是否存在。

程序性能更好。因为这种方式无须调用方法,所以性能更好。

也就是说,大部分时候我们都应该使用第二种方式来获取指定类的Class对象。但如果我们只有一个字符串,例如“java.lang.String”,若需要获取该字符串对应的Class对象,则只能使用第一种方式,使用Class的forName(String clazzName)方法获取Class对象时,该方法可能抛出一个ClassNotFoundException异常。一旦获得了某个类所对应的Class对象之后,程序就可以调用Class对象的方法来获得该对象和该类的真实信息了。

4. Class类 API介绍

通过class类我们能够获取大量的信息:

获取构造函数

Connstructor getConstructor(Class<?>... parameterTypes):返回此Class对象对应类的指定public构造器。

Constructor<?>[] getConstructors():返回此Class对象对应类的所有public构造器。

Constructor getDeclaredConstructor(Class<?>... parameterTypes):返回此Class对象对应类的指定构造器,与构造器的访问权限无关。

Constructor<?>[] getDeclaredConstructors():返回此Class对象对应类的所有构造器,与构造器的访问权限无关。

获取方法

Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回此Class对象对应类的指定方法,与方法的访问权限无关。

Method[] getDeclaredMethods():返回此Class对象对应类的全部方法,与方法的访问权限无关。

获取属性

Field getField(String name):返回此Class对象对应类的指定public Field。

Field[] getFields():返回此Class对象对应类的所有public Field。

Field getDeclaredField(String name):返回此Class对象对应类的指定Field,与Field的访问权限无关。

Field[] getDeclaredFields():返回此Class对象对应类的全部Field,与Field的访问权限无关。

获取Class对应类上所包含的Annotation。

A getAnnotation(Class annotationClass):试图获取该Class对象对应类上指定类型的Annotation;如果该类型的注释不存在,则返回null。

Annotation[] getAnnotations():返回该Class对象对应类上的所有Annotation。

Annotation[] getDeclaredAnnotations():返回直接修饰该Class对应类的所有Annotation。

获取Class对象对应类包含的内部类。

Class<?>[] getDeclaredClasses():返回该Class对象对应类里包含的全部内部类。
如下方法用于访问该Class对象对应类所在的外部类。

Class<?> getDeclaringClass():返回该Class对象对应类所在的外部类。
如下方法用于访问该Class对象对应类所继承的父类、所实现的接口等。

Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口。

获取Class对象对应类所继承的父类

Class<? super T> getSuperclass():返回该Class对象对应类的超类的Class对象。

获取Class对象对应类的修饰符、所在包、类名等基本信息。

int getModifiers():返回此类或接口的所有修饰符。修饰符由public、protected、private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获取真实的修饰符。

Package getPackage():获取此类的包。

String getName():以字符串形式返回此Class对象所表示的类的名称。

String getSimpleName():以字符串形式返回此Class对象所表示的类的简称。

判断该类是否为接口、枚举、注释类型等

boolean isAnnotation():返回此Class对象是否表示一个注释类型(由@interface定义)。

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判断此Class对象是否使用了Annotation注释修饰。

boolean isAnonymousClass():返回此Class对象是否是一个匿名类。

boolean isArray():返回此Class对象是否表示一个数组类。

boolean isEnum():返回此Class对象是否表示一个枚举(由enum关键字定义)。

boolean isInterface():返回此Class对象是否表示一个接口(使用interface定义)。

boolean isInstance(Object obj):判断obj是否是此Class对象的实例,该方法可以完全代替instanceof操作符。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgzwp.html