反射
一、Java的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二、关键点-获取Class文件对象
Properties p = new Properties(); p.load(Test01.class.getClassLoader().getResourceAsStream("classPath.properties")); String path = p.getProperty("path"); Class<?> clazz = Class.forName(path); //获取本类及其父类公有的方法对象 Method[] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } //获取本类所有的方法对象 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } //获取本类及其父类的所有对象 for(Class<?> c = clazz; c != null; c = c.getSuperclass()) { Method[] methods = c.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } } //获取本类公有的指定名字的方法对象 Method method = clazz.getMethod("setClassId",String.class); System.out.println(method); //利用反射工具类获取子类及其父类指定名字的方法对象 Method method = ReflexUtil.getMethod(clazz, "method"); System.out.println(method); //获取方法参数值 int modifiers = method.getModifiers(); System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers)); System.out.println("是否使用static修饰:" + Modifier.isStatic(modifiers)); System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers)); System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers)); System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers)); System.out.println("是否使用abstract修饰:" + Modifier.isAbstract(modifiers)); System.out.println("是否使用synchronized修饰:" + Modifier.isSynchronized(modifiers)); }
三、利用反射操作方法
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Properties p = new Properties(); p.load(Test01.class.getClassLoader().getResourceAsStream("classPath.properties")); String path = p.getProperty("path"); Class<?> clazz = Class.forName(path); //利用反射调用静态方法 Method method = ReflexUtil.getMethod(clazz, "method"); method.invoke(null);//静态方法不需要对象调用,就传入null Student stu = new Student(); //利用反射调用成员方法 -- 无参数无返回值的方法 Method method01 = ReflexUtil.getMethod(clazz, "method01"); method01.invoke(stu); //利用反射调用成员方法 -- 带参数的方法 Method method02 = ReflexUtil.getMethod(clazz, "method02", String.class,int.class); method02.invoke(stu, "好好学习,天天向上",100); //利用反射调用成员方法 -- 无参数带返回值的方法 Method method03 = ReflexUtil.getMethod(clazz, "method03"); String returnVal1 = (String) method03.invoke(stu); System.out.println(returnVal1); //利用反射调用成员方法 -- 带参数带返回值的方法 Method method04 = ReflexUtil.getMethod(clazz, "method04", String.class,int.class); method04.setAccessible(true);//调用私有的成员方法是需要设置修改权限 String returnVal2 = (String)method04.invoke(stu, "好好学习,天天向上",200); System.out.println(returnVal2); //利用反射工具类 -- 调用静态方法 ReflexUtil.invoke(clazz, "method", null, null); Student stu = new Student(); //利用反射工具类 -- 反射调用成员方法 -- 无参数无返回值的方法 ReflexUtil.invoke(stu, "method01", null, null); //利用反射工具类 -- 反射调用成员方法 -- 带参数的方法 ReflexUtil.invoke(stu, "method02", new Class[] {String.class,int.class}, new Object[] {"好好学习,天天向上",100}); //利用反射工具类 -- 反射调用成员方法 -- 无参数带返回值的方法 Object returnVal1 = ReflexUtil.invoke(stu, "method03", null, null); System.out.println(returnVal1); //利用反射工具类 -- 反射调用成员方法 -- 带参数带返回值的方法 Object returnVal2 = ReflexUtil.invoke(stu, "method04", new Class[] {String.class,int.class}, new Object[] {"好好学习,天天向上",100}); System.out.println(returnVal2); }
四、利用反射操作方法里的参数和返回值
public static void main(String[] args) throws IOException, ClassNotFoundException { Properties p = new Properties(); p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties")); String path = p.getProperty("path"); Class<?> clazz = Class.forName(path); //利用反射工具类获取方法对象 Method method = ReflexUtil.getMethod(clazz, "method04", String.class,int.class); //获取方法的参数个数 int parameterCount = method.getParameterCount(); System.out.println("获取方法的参数个数:" + parameterCount); System.out.println("------------------------------------"); //获取方法参数的class对象数组 Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> c : parameterTypes) { System.out.println(c); } System.out.println("------------------------------------"); //获取方法参数的Type对象数组 //一个参数类型就是一个Type对象 Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type type : genericParameterTypes) { System.out.println(type); System.out.println("------------------------------------"); } //获取方法参数对象数组 //一个参数就是一个参数对象 Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { System.out.println("获取方法的参数类型" + parameter.getType()); /** * 注意:参数名不会随着编译而编译到class文件 * class文件描述该方法的参数名使用的是:arg0,arg1,arg2... */ System.out.println("获取方法的参数名" + parameter.getName()); } System.out.println("------------------------------------"); //获取返回值的class对象 Class<?> returnType = method.getReturnType(); System.out.println("获取返回值的class对象:" + returnType); //获取返回值的Type对象 Type genericReturnType = method.getGenericReturnType(); System.out.println("获取返回值的type对象:" + genericReturnType); }
五、利用反射操作泛型
public static void main(String[] args) throws IOException, ClassNotFoundException { Properties p = new Properties(); p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties")); String path = p.getProperty("path"); Class<?> clazz = Class.forName(path); //获取属性上的泛型类型 Field field = ReflexUtil.getField(clazz, "map"); Type fieldType = field.getGenericType(); ParameterizedType fieldTypePT = (ParameterizedType) fieldType; Type[] actualTypeArguments = fieldTypePT.getActualTypeArguments(); for (Type type : actualTypeArguments) { System.out.println(type); } System.out.println("---------------------------"); Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class); //获取方法参数上的泛型类型 Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { Type parameterizedType = parameter.getParameterizedType(); ParameterizedType parameterTypePT = (ParameterizedType) parameterizedType; Type[] actualTypeArguments2 = parameterTypePT.getActualTypeArguments(); for (Type type : actualTypeArguments2) { System.out.println(type); } } System.out.println("---------------------------"); //获取方法上返回值的泛型类型 Type genericReturnType = method.getGenericReturnType(); ParameterizedType returnPT = (ParameterizedType) genericReturnType; Type[] actualTypeArguments2 = returnPT.getActualTypeArguments(); for (Type type : actualTypeArguments2) { System.out.println(type); } }
六、利用反射操作注解
public static void main(String[] args) throws IOException, ClassNotFoundException { Properties p = new Properties(); p.load(Test05.class.getClassLoader().getResourceAsStream("classPath.properties")); String path = p.getProperty("path"); Class<?> clazz = Class.forName(path); //获取类上的注解信息 MyAnnotaction classAnnotation = clazz.getAnnotation(MyAnnotaction.class); System.out.println(classAnnotation.str()); System.out.println("--------------------"); //获取属性上的注解信息 Field field = ReflexUtil.getField(clazz, "map"); MyAnnotaction fieldAnnotation = field.getAnnotation(MyAnnotaction.class); System.out.println(fieldAnnotation.str()); System.out.println("--------------------"); //获取方法上的注解信息 Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class); MyAnnotaction methodAnnotation = method.getAnnotation(MyAnnotaction.class); System.out.println(methodAnnotation.str()); System.out.println("--------------------"); //获取参数上的注解信息 Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { MyAnnotaction parameterAnnotation = parameter.getAnnotation(MyAnnotaction.class); if(parameterAnnotation != null) {//说明该参数上有MyAnnotaction的注解 System.out.println(parameterAnnotation.str()); } } }
七、利用反射操作数组
public static void main(String[] args) { //创建数组 int[] arr = (int[]) Array.newInstance(int.class, 10); //获取数组长度 int length = Array.getLength(arr); System.out.println("获取数组长度:" + length); //循环设置每个下标上的元素 for (int i = 0; i < Array.getLength(arr); i++) { //设置当前下标上的元素 Array.set(arr, i, i+1); } //循环设置每个下标上的元素 for (int i = 0; i < Array.getLength(arr); i++) { //获取当前下标上的元素 Object element = Array.get(arr, i); System.out.println(element); } }