一、概述
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(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定名(必须添加完整包名)。
2.调用某个类的class属性来获取该类对应的Class对象。
3.调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法。
1 2 3 4 5 6 7
| class1 = Class.forName("com.lvr.reflection.Person"); class1 = Person.class; Person person = new Person(); Class<?> class1 = person.getClass();
|
获取class对象的属性、方法、构造函数等
1.获取class对象的成员变量
1 2 3 4
| Field[] allFields = class1.getDeclaredFields(); Field[] publicFields = class1.getFields(); Field ageField = class1.getDeclaredField("age"); Field desField = class1.getField("des");
|
2.获取class对象的方法
1 2 3 4
| Method[] methods = class1.getDeclaredMethods(); Method[] allMethods = class1.getMethods(); Method method = class1.getMethod("info", String.class); Method declaredMethod = class1.getDeclaredMethod("info", String.class);
|
3.获取class对象的构造函数
1 2 3 4
| Constructor<?>[] allConstructors = class1.getDeclaredConstructors(); Constructor<?>[] publicConstructors = class1.getConstructors(); Constructor<?> constructor = class1.getDeclaredConstructor(String.class); Constructor publicConstructor = class1.getConstructor(String.class);
|
4.其他方法
1 2 3 4
| Annotation[] annotations = (Annotation[]) class1.getAnnotations(); Annotation annotation = (Annotation) class1.getAnnotation(Deprecated.class); Type genericSuperclass = class1.getGenericSuperclass(); Type[] interfaceTypes = class1.getGenericInterfaces();
|
获取class对象的信息
比较多。
1 2 3 4 5 6 7 8 9 10 11 12 13
| boolean isPrimitive = class1.isPrimitive(); boolean isArray = class1.isArray(); boolean isAnnotation = class1.isAnnotation(); boolean isInterface = class1.isInterface(); boolean isEnum = class1.isEnum(); boolean isAnonymousClass = class1.isAnonymousClass(); boolean isAnnotationPresent = class1.isAnnotationPresent(Deprecated.class); String className = class1.getName(); Package aPackage = class1.getPackage(); String simpleName = class1.getSimpleName(); int modifiers = class1.getModifiers(); Class<?>[] declaredClasses = class1.getDeclaredClasses(); Class<?> declaringClass = class1.getDeclaringClass();
|
三、通过Java反射生成并操作对象
生成类的实例对象
1.使用Class对象的newInstance()方法来创建该Class对象对应类的实例。这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法时实际上是利用默认构造器来创建该类的实例。
2.先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。
1 2 3 4 5
| Object obj = class1.newInstance(); Constructor<?> constructor = class1.getDeclaredConstructor(String.class); obj = constructor.newInstance("hello");
|
调用类的方法
1.通过Class对象的getMethods()方法或者getMethod()方法获得指定方法,返回Method数组或对象。
2.调用Method对象中的Object invoke(Object obj, Object... args)
方法。第一个参数对应调用该方法的实例对象,第二个参数对应该方法的参数。
1 2 3 4 5 6
| Object obj = class1.newInstance(); Method method = class1.getDeclaredMethod("setAge", int.class); method.invoke(obj, 28);
|
当通过Method的invoke()方法来调用对应的方法时,Java会要求程序必须有调用该方法的权限。如果程序确实需要调用某个对象的private方法,则可以先调用Method对象的如下方法。
setAccessible(boolean flag):将Method对象的acessible设置为指定的布尔值。值为true,指示该Method在使用时应该取消Java语言的访问权限检查;值为false,则知识该Method在使用时要实施Java语言的访问权限检查。
访问成员变量值
1.通过Class对象的getFields()方法或者getField()方法获得指定方法,返回Field数组或对象。
2.Field提供了两组方法来读取或设置成员变量的值:
getXXX(Object obj):获取obj对象的该成员变量的值。此处的XXX对应8种基本类型。如果该成员变量的类型是引用类型,则取消get后面的XXX。
setXXX(Object obj,XXX val):将obj对象的该成员变量设置成val值。
1 2 3 4 5 6 7 8
| Object obj = class1.newInstance(); Field field = class1.getField("age"); field.setInt(obj, 10); field.getInt(obj);
|