反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法等成员。
前提:使用反射机制的前提条件是获取字节码文件对象,即Class类型对象.
获取Class对象的三种方式:
1:通过 类名.class 获取
eg:Class c = Student.class;
2:通过Object类的getClass()方法获取
eg:Student stu = new Student(); Class c = stu.getClass();
3:通过Class.forName(“权限定类型”)获取
eg: String className = "com.yxx.bean.Student"; Class clazz = Class.forName(className);
Class对象相关方法 :
String getSimpleName(); | 获得简单类名,只是类名,没有包 |
String getName(); | 获取完整类名,包含包名+类名 |
T newInstance() ; | 创建此 Class 对象所表示的类的一个新实例。 要求:类必须有public的无参数构造方法 |
反射获取Class对象的Constructor方法:
Constructor getConstructor(Class... parameterTypes) | 根据参数类型获取构造方法对象,只能获得public修饰的构造方法。 如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。 |
Constructor getDeclaredConstructor(Class... parameterTypes) | 根据参数类型获取构造方法对象,包括private修饰的构造方法。 如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。 |
Constructor[] getConstructors() | 获取所有的public修饰的构造方法 |
Constructor[] getDeclaredConstructors() | 获取所有构造方法,包括privat修饰的 |
T newInstance(Object... initargs) | 根据指定参数创建对象。 |
void setAccessible(true) | 暴力反射,设置为可以直接访问私有类型的构造方法。 |
反射获取Class对象的Method方法:
Method getMethod("方法名", 方法的参数类型... 类型) | 根据方法名和参数类型获得一个方法对象,只能是获取public修饰的 |
Method getDeclaredMethod("方法名", 方法的参数类型... 类型) | 根据方法名和参数类型获得一个方法对象,包括private修饰的 |
Method[] getMethods() | 获取所有的public修饰的成员方法,包括父类中。 |
Method[] getDeclaredMethods() | 获取当前类中所有的方法,包含私有的,不包括父类中。 |
Object invoke(Object obj, Object... args) | 根据参数args调用对象obj的该成员方法 如果obj=null,则表示该方法是静态方法 |
void setAccessible(boolean flag) | 暴力反射,设置为可以直接调用私有修饰的成员方法 |
反射获取Class对象的Field方法:
Field getDeclaredField(String name) | 根据属性名获得属性对象,包括private修饰的 |
Field getField(String name) | 根据属性名获得属性对象,只能获取public修饰的 |
Field[] getFields() | 获取所有的public修饰的属性对象,返回数组。 |
Field[] getDeclaredFields() | 获取所有的属性对象,包括private修饰的,返回数组。 |
注解
-
属性的作用 可以让用户在使用注解时传递参数,让注解的功能更加强大。
-
属性的格式
格式1:数据类型 属性名();
格式2:数据类型 属性名() default 默认值;
3.属性适用的数据类型
八种基本数据类型(int,flfloat,boolean,byte,double,char,long,short)
String类型,Class类型,枚举类型,注解类型
以上所有类型的一维数组
元注解
@Target | |
---|---|
作用: | 指明此注解用在哪个位置,如果不写默认是任何地方都可以使用。 |
可选的参数值在枚举类ElemenetType中包括: | TYPE: 用在类,接口上 FIELD:用在成员变量上 METHOD: 用在方法上 PARAMETER:用在参数上 CONSTRUCTOR:用在构造方法上 LOCAL_VARIABLE:用在局部变量上 |
@Retention | |
---|---|
作用: | 定义该注解的生命周期(有效范围)。 |
可选的参数值在枚举类型RetentionPolicy中包括 | SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了 CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值。 RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该 注解。 |
注解的接口
1.Anontation:所有注解类型的公共接口,类似所有类的父类是Object。
2.AnnotatedElement:定义了与注解解析相关的方法,常用方法以下几个
boolean isAnnotationPresent(Class annotationClass); | 判断当前对象是否有指定的注解,有则返回true,否则返回false。 |
T getAnnotation(Class<T> annotationClass); | 获得当前对象上指定的注解对象。 |
Annotation[] getAnnotations(); | 获得当前对象及其从父类上继承的所有的注解对象。 |
我们使用反射的时候 , 都需要先获取类的字节码对象 ,最常用的方式就是 Class.forName("类的全限定名") .我们可以通过字节码对象就可以获取类的构造器 , 从而创建对象 ,最常用的方式是通过字节码对象获取无参构造器getConstructor , 就可以调用构造器对象的 newInstance() 方法创建对象 , 当然这种方式简化为:字节码对象直接调用 newInstance() 方法创建对象 .也可以通过字节码对象获取指定的方法 , 然后调用方法对象的 invoke(Object obj, Object... args) 来执行此方法.也可以通过字节码对象获取类中的所有字段 , 从而给字段赋值和获取字段的值 .有了以上的基础 , 我们就可以通过一个指定全限定名 , 就可以创建该类对象的实例对象 , 执行里面的方法 , 给其字段进行赋值或者获取值.