本文共 5231 字,大约阅读时间需要 17 分钟。
在运行状态中,对于任何一个类都能知道这个类中的所有属性、方法;对于任意一个对象,都能调用它的属性、方法;这种动态获取信息以及动态调用对象方法的功能,称之为反射。
类被加载后,会生成一个对应的Class对象。通过Class对象,就能访问到JVM中的这个类。获取Class对象,概括分为3中方式:
//通过静态方法forName实现 class = Class.forName(com.xxx.xxx.Person); //通过class属性 class = Person.class; //通过对象的getClass方法 Person person = new Person(); Class class = person.getClass();
a.获取class对象的成员变量
Field[] allFields = class1.getDeclaredFields();//获取class对象所有属性 Field ageField = class1.getDeclaredField("age");//获取指定属性 Field[] PublicFields = class1.getFields();//获取public属性 Field desField = class1.getField("age");//获取指定的public属性
b.获取class对象方法
Method[] methods = class1.getDeclaredMethods();//获取所有方法 Method declaredMethod = class1.getDeclaredMethod("info", String.class);//返回带指定形参列表的方法 Method[] allMethods = class1.getMethods();//返回所有public方法 Method method = class1.getMethod("info", String.class);//返回带指定形参列表的pulic方法
c.获取class对象构造函数
Constructor [] allConstructors = class1.getDeclaredConstructors();//返回所有构造方法 Constructor constructor = class1.getDeclaredConstructor(String.class);//获取指定声明的构造方法 Constructor [] publicConstructors = class1.getConstructors();//返回所有public构造方法 Constructor publiconstructor = class1.getConstructor(String.class);//返回指定的public构造方法
d.其他方法
Annotation[] annotations = (Annotation[]) class1.getAnnotations();//获取class对象所有注解 Annotation annotation = (Annotation) class1.getAnnotation(Deprecated.class);//获取指定注解 Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类type Type[] genericInterfaces = class1.getGenericInterfaces();//获取class对象所有接口的type结婚
boolean primitive = class1.isPrimitive();//是否是基础类型 boolean array = class1.isArray();//是否是集合类 boolean annotation = class1.isAnnotation();//是否是注解类 boolean anInterface = class1.isInterface();//是否是接口类 boolean anEnum = class1.isEnum();//是否是枚举类 boolean anonymousClass = class1.isAnonymousClass();//是否是匿名内部类 boolean annotationPresent = class1.isAnnotationPresent(Deprecated.class);//是否被某个注解类修饰 String name = class1.getName();//获取class的name,包括包路径 Package aPackage = class1.getPackage();//获取包信息 String simpleName = class1.getSimpleName();//获取class类名 int modifiers = class1.getModifiers();//获取访问权限 Class [] declaredClasses = class1.getDeclaredClasses();//内部类 Class declaringClass = class1.getDeclaringClass();//外部类
//调用newInstance()生成 Object obj = class1.newInstance(); //通过构造方法在调用newInstance()生成 Constructor constructor = class1.getDeclaredConstructor(String.class); Object obj = constructor.newInstance("hello");
Object obj = class1.newInstance();//生成新的对象 Method method = class1.getDeclaredMethod("setAge", int.class);//获取与该方法对应的Method对象 method.invoke(obj,11);//调用指定函数并传参
通过Method的invoke方法来调用对应方法时,程序必须要有调用该方法的权限。如果需要调用某个对象的private方法,可先调用setAcccessible(boolean flag);true代表Method在使用时取消访问权限检查,false表示启用访问权限检查。
Object obj = class1.newInstance();//生成新的对象 Field field = class1.getField("age");//获取age变量 field.setInt(obj,10);//将age设置10 field.getInt(obj);//取出age
在反射中使用泛型,可以避免反射生成的对象需要强制类型转换。
//工厂类public class ObjectFactory { public staticT getInstance(Class cls){ try { return cls.newInstance(); } catch (InstantiationException |IllegalAccessException e) { e.printStackTrace(); return null; } }}
此时传入String.class,T便代表String,返回的对象是String类型,避免了强制类型转换
String instance = ObjectFactory.getInstance(String.class);
通过类对应的Class对象,可以获取到所有的Field,并获得Field类型:
//获取field对象f的类型Class a = f.getType();
如果Field类型是有泛型限制的类型,如Map<String,Integer>,就不灵了。只能先获取Field类型,再把type对象强制转换为ParameterizedType(代表被参数化的类型,即增加了泛型限制的类型)对象,ParameterizedType提供了getRawType()(返回没有泛型信息的原始类型)和getActualTypeArguments()(返回泛型参数的类型)
public class GenericTest { private Mapscore; public static void main(String []args) throws Exception { Class clazz = GenericTest.class; Field f = clazz.getDeclaredField("score"); //直接使用getType取出Field类型,只对普通类型的Field有效 Class a = f.getType(); System.out.println("score类型为"+a); //获取Field实例f的泛型类型 Type gType = f.getGenericType(); //如果gType类型时ParameterizedType if (gType instanceof ParameterizedType){ ParameterizedType pType = (ParameterizedType) gType; //获取原始类型 Type rType = pType.getRawType(); System.out.println("原始类型时"+rType); //获取泛型类型的泛型参数 Type[] tArgs = pType.getActualTypeArguments(); for (int i = 0; i < tArgs.length; i++) { System.out.println(i+"个泛型类型是:"+tArgs[i]); } }else { System.out.println("获取泛型类型出错"); } }}
以上输出结果:
score类型为interface java.util.Map 原始类型时interface java.util.Map 0个泛型类型是:class java.lang.String 1个泛型类型是:class java.lang.Integer1.逆向编码,如反编译
2.与注解相结合的框架,如Retrofit 3.单纯的反射机制应用框架,如EventBus 4.动态生成类框架,如Gson转载地址:http://wnbq.baihongyu.com/