反射 基本应用
public class ClassUtil { public static void printClassMethodMessage(Object obj) { Class c = obj.getClass(); System.out.println(c.getName()); /** * Method类,方法对象 * getMethods()方法获取的是所有的public的函数,包括父类继承而来的 * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问的权限 */ Method [] methods = c.getMethods(); for(int i=0; i<methods.length; i++) { //获取方法的返回值类型的类类型 Class returnType = methods[i].getReturnType(); //例如 String.class System.out.print(returnType.getName() + " "); //获取方法的名字 System.out.print(methods[i].getName() + "("); //获取参数类型--->得到的是参数列表的类型的类类型 Class [] params = methods[i].getParameterTypes(); for(Class class1 : params) { System.out.print(class1.getName() + ","); } System.out.println(")"); } printFieldMessage(c); } private static void printFieldMessage(Object object) { /** * 成员变量也是对象 * java.lang.reflect.Field * Field类封装了关于成员变量的操作 * getFields()方法获取的是所有的public的成员变量 * getDeclaredFields() 获取的是该类自己声明的成员变量的信息 */ Class c = object.getClass(); Field [] fs = c.getFields(); for(Field field : fs) { //获取成员变量 的类型的类类型 Class fieldType = field.getType(); //获取成员变量类型的名字 String typeName = fieldType.getName(); //成员变量的名称 String fieldName = field.getName(); System.out.println(typeName + " " + fieldName); } } /** * 打印构造函数的信息 * @param obj */ private static void printConMessage(Object obj) { Class c = obj.getClass(); /** * 构造函数也是对象 * java.lang.Constructor 中封装了构造函数的信息 * getConstructor 获取所有的public的构造函数 * getDeclaredConstuctors得到所有的构造函数 */ Constructor [] cs = c.getDeclaredConstructors(); for(Constructor constructor : cs) { System.out.print(constructor.getName() + "("); //获取构造函数的参数列表 --> 得到的是参数列表的类的类类型 Class [] paramTypes = constructor.getParameterTypes(); for(Class class1 : paramTypes) { System.out.print(class1.getName() + ","); } System.out.println(")"); } } public static void main(String [] args) { String string = "qqq"; // printClassMethodMessage(string); // // printConMessage(string); /** * 获取方法 名称和参数列表来决定 * getMethod获取的是public方法 * getDelcaredMethod自己声明的方法 * * */ A a = new A(); Class class1 = a.getClass(); try { Method m1 = class1.getDeclaredMethod("print"); //方法如果没有返回值返回null,有返回值返回具体的返回值 Object object = m1.invoke(a); System.out.println("========================"); Method m2 = class1.getDeclaredMethod("print", new Class [] {int.class,int.class}); Object object2 = m2.invoke(a, 10,20); System.out.println("========================"); Method m3 = class1.getDeclaredMethod("print", String.class,String.class); Object object3 = m3.invoke(a, "hello","world"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class A{ public A() { } public void print() { System.out.println("hello world"); } public void print(int a,int b) { System.out.println(a+b); } public void print(String a,String b) { System.out.println(a.toLowerCase() + b.toUpperCase()); } }
反射是可以绕过编译来执行的
public class Demo { public static void main(String [] args) { ArrayList list = new ArrayList(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("hello"); //list1.add(20); Class c1 = list.getClass(); Class c2 = list1.getClass(); System.out.println(c1 == c2); //反射都是编译后的操作 /** * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的 * Java中集合的泛型,是防止错误的输入,只在编译阶段有效 * 绕过编译就无效了 * 验证:通过方法的反射来操作,绕过编译 */ try { Method method = c1.getMethod("add",Object.class); method.invoke(list1, 100); System.out.println(list1.size()); System.out.println(list1); /** * 本来list1的类型是String的 加了100后 就不能用foreach遍历了 * */ }catch (Exception e) { // TODO: handle exception } } }