反射
一、关于
反射:即将类的各个组成部分封装为其他对象。它是发生在程序运行期间的行为,使用反射可以使代码更动态,更灵活,便于后期维护。
二、可以实现以下功能
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理
三、获取Class对象的方式
- Class.forName("包名+类名"):将字节码文件加载进内存,返回Class对象(推荐使用)
-
Class cls4=Class.forName("java.lang.String"); System.out.println(cls3==cls4);
- 类名.class:通过类名的属性class获取
-
Class cls3=String.class; System.out.println(cls1==cls3);
- 对象.getClass()
-
Class cls1="哈哈".getClass(); Class cls2="呵呵".getClass(); System.out.println(cls1.toString()); System.out.println(cls1==cls2); //一个类只有一个Class对象
注: 同一个字节码文件在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
四、常用方法
(1)、获取构造器的方法
方法 作用 getConstructor(Class…<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法 getConstructors() 获得该类的所有公有构造方法 getDeclaredConstructor(Class…<?> parameterTypes) 获得该类中与参数类型匹配的构造方法 getDeclaredConstructors() 获得该类所有构造方法 (2)、获得类中方法的方法
方法 作用 getMethod(String name, Class…<?> parameterTypes) 获得该类某个公有的方法 getMethods() 获得该类所有公有的方法 getDeclaredMethod(String name, Class…<?> parameterTypes) 获得该类某个方法 getDeclaredMethods() 获得该类所有方法 (3)、获取类中属性的方法
方法 作用 getField(String name) 获得某个公有的属性对象 getFields() 获得所有公有的属性对象 getDeclaredFields() 获得所有属性对象 getDeclaredField(String name) 获得某个属性对象 案例:
public static void testConstructor(Class cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{ //1.创建对象 Object obj=cls.newInstance(); //获取所有的公共的构造器 Constructor[] cons=cls.getConstructors(); System.out.println(Arrays.toString(cons)); //指明创建对象的时候使用该构造器初始化信息 Object user=cons[0].newInstance(1234); System.out.println(user); //获取某一个构造器,包括私有的 Constructor con=cls.getDeclaredConstructor(String.class,int.class); con.setAccessible(true); //放开权限 Object user2=con.newInstance("张三",123); con.setAccessible(false); //关闭权限 System.out.println(user2); } /* * 属性 * 2个获取公共的字段 * 2个所有的字段 * 给属性设置值 void set(Object obj, Object value) * 获取属性的值 get(obj) */ public static void testField(Class cls) throws Exception{ User user=(User) cls.newInstance(); //获取属性 私有的需要打开 Field field=cls.getDeclaredField("name"); field.setAccessible(true); //给属性设置值 field.set(user, "李四"); //通过反射获取私有字段的值 System.out.println(field.get(user)); field.setAccessible(false); Field field2=cls.getDeclaredField("a"); field2.set(user, 10); System.out.println(field2.get(null)); } /* * 方法 * 调用方法 * Object invoke(Object obj, Object... args) * 返回值:调用方法的返回值,没有返回值,结果为null * 参数: * 1) 调用方法成员的对象 * 2) 调用方法的实参 */ public static void testMethod(Class cls) throws Exception{ Method method=cls.getDeclaredMethod("haha"); method.setAccessible(true); Object obj=method.invoke(null); System.out.println(obj); } /*反射操作数组: * static Object newInstance(Class<?> componentType, int length) 创建一个具有指定的组件类型和长度的新数组。 * static void set(Object array, int index, Object value) * static Object get(Object array, int index) 返回指定数组对象中索引组件的值。 */ public static void testArray() throws Exception{ int[] arr=(int[]) Array.newInstance(int.class, 8); System.out.println(Arrays.toString(arr)); Array.set(arr, 1, 1); System.out.println(Arrays.toString(arr)); System.out.println(arr.getClass().isArray()); }