什么是反射
反射是java系统的API,它允许程序在运行过程中取得任何一个已知名称的类的内部信息,包括其中的构造方法,声明的字段和定义的方法等。利用反射API可以实现动态执行:
动态加载类,获取信息
动态创建对象
动态访问属性
动态调用方法
反射相关方法
public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // 一个类只可能是Class类的一个实例对象 Aoo f = new Aoo(); Class c1 = Aoo.class; Class c2 = f.getClass(); Class c3 = Class.forName("com.day11.oopqueue.Aoo"); System.out.println(c1 == c2 && c1 == c3 && c2 == c3 ? "三种方法所获取的Class类类型全相同" : "不全相同"); // 通过类的类类型创建该类的一个实例 Aoo f2 = (Aoo) c1.newInstance(); f2.print(); }}class Aoo { void print() { System.out.println("对象Aoo的一个实例"); }}
-----------------------------------------------------------------------------------
public class ReflectDemo2 { public static void main(String[] args) { Class c1 = int.class; // int的类类型 Class c2 = String.class; Class c3 = double.class; Class c4 = Double.class; Class c5 = void.class; System.out.println(c2.getName()); //java.lang.String System.out.println(c2.getSimpleName());// String }
}
----------------------------------------------------------------------------------
动态获取类属性方法
public class ReflectDemo3 { public static void main(String[] args) { String str = "Hello World"; ReflectDemo3.printClassMethodMessage(str); System.out.println("===================================================="); Integer n = 1; ReflectDemo3.printFieldMessage(n); } // 打印类的信息,包括类的成员函数、成员变量 public static void printClassMethodMessage(Object obj) { Class c = obj.getClass(); // 获取类的名称 System.out.println("类的名称是:" + c.getName()); // getMethods()方法获取的是所有的public的函数,包括父类继承而来的 Method[] ms = c.getMethods(); for (int i = 0; i < ms.length; i++) { // 得到方法的返回值类型的类类型 Class returnType = ms[i].getReturnType(); System.out.print(returnType.getName() + " "); // 得到方法的名称 System.out.print(ms[i].getName() + "("); // 获取参数列表的类型的类类型 Class[] paramTypes = ms[i].getParameterTypes(); for (Class cls : paramTypes) System.out.print(cls.getName() + ","); System.out.println(")"); printFieldMessage(c); } } // 获取成员变量的信息 public static void printFieldMessage(Object obj) { Class c = obj.getClass(); Field[] fs = c.getDeclaredFields(); for (Field field : fs) { // 得到成员变量的类型的类类型 Class fieldType = field.getType(); String typeName = fieldType.getName(); // 得到成员变量的名称 String fieldName = field.getName(); System.out.println(typeName + " " + fieldName); } } // 打印对象的构造函数的信息 public static void printConMessage(Object obj) { Class c = obj.getClass(); Constructor[] cs = c.getDeclaredConstructors(); for (Constructor constructor : cs) { System.out.print(constructor.getName() + "("); // 获取构造函数的参数类表 Class[] paramTypes = constructor.getParameterTypes(); for (Class cls : paramTypes) System.out.print(cls.getName() + ","); System.out.println(")"); } }
}
----------------------------------------------------------------------------------
动态调用方法
public class ReflectDemo4 { public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { C coo = new C(); Class c = coo.getClass(); Method m = c.getMethod("print", int.class, int.class); Object o = m.invoke(coo, 10, 20); System.out.println("====================="); Method m1 = c.getMethod("print", String.class, String.class); o = m1.invoke(coo, "hello", "World"); System.out.println("====================="); Method m2 = c.getMethod("print"); m2.invoke(coo); }}class C { public void print() { System.out.println("HelloWorld"); } public void print(int a, int b) { System.out.println(a + b); } public void print(String a, String b) { System.out.println(a.toUpperCase() + "," + b.toLowerCase()); }
}
---------------------------------------------------------------------------------
反射绕过泛型,对泛型进行擦除
public class ReflectDemo5 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { ArrayList list1 = new ArrayList(); ArrayList<String> list2 = new ArrayList<String>(); list2.add("hello"); Class c1 = list1.getClass(); Class c2 = list2.getClass(); // true说明集合的泛型是去泛型化的,只在编译阶段有效 // 反射的操作时在编译之后的操作 System.out.println(c1 == c2); Method m = c2.getMethod("add", Object.class); m.invoke(list2, 1); System.out.println(list2); } }