概念
- 反射机制是在
运行状态
中:
对于任意一个类,都能够知道这个类的所有属性和方法。
对于任意一个对象,都能够调用它的任意一个方法和属性。
提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
获得反射入口的三种方式(获得类)
Class.forName(全类名)(推荐使用)
1 2 3 4 5 6
| try { Class<?> classStu = Class.forName("reflect.Student"); System.out.println(classStu); } catch (ClassNotFoundException e) { e.printStackTrace(); }
|
类名.class
1 2
| Class<?> classStu2 = Student.class; System.out.println(classStu2);
|
对象.getClass()
1 2 3
| Student stu = new Student(); Class<?> classStu3 = stu.getClass(); System.out.println(classStu3);
|
通过反射获取类的相关信息
获取所有的公共的方法
- 方法范围是本类以及父类、接口中的所有公有的方法
- 符合访问修饰的规律
1 2 3 4
| Method[] methods = classStu.getMethods(); for(Method method : methods) { System.out.println(method); }
|
获取该类的所有接口
1 2 3 4
| Class<?>[] interfaces = classStu.getInterfaces(); for(Class<?> inter : interfaces) { System.out.println(inter); }
|
获取该类的父类
1 2
| Class<?> superClass = classStu.getSuperclass(); System.out.println(superClass);
|
获取该类的所有的构造方法
1 2 3 4
| Constructor<?>[] constructors = classStu.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); }
|
获取所有公共属性
1 2 3 4
| Field[] fields = classStu.getFields(); for (Field field : fields) { System.out.println(field); }
|
获取当前类的所有方法
- 包含私有方法(忽略访问修饰符)
- 不包括父类方法,但包含接口的实现方法
1 2 3 4
| Method[] declaredMethods = classStu.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); }
|
获取当前类的所有属性
1 2 3 4
| Field[] declaredFields = classStu.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); }
|
获取当前反射所代表类(接口)的对象(实例)
1 2 3
| Object newInstance = classStu.newInstance(); Student stu = (Student)newInstance; stu.breathe();
|
通过反射获取对象的实例,并操作对象(实例)
操作属性
1 2 3 4 5
| Student stu = (Student)classStu.newInstance(); Field idFieAge = classStu.getDeclaredField("age"); idFieAge.setAccessible(true);//修改访问权限(private) idFieAge.set(stu, 1);//相当于stu.setAge(1); System.out.println(stu.getAge());
|
操作函数
1 2 3 4
| Student stu = (Student)classStu.newInstance(); Method method = classStu.getDeclaredMethod("sleep", null);//(函数名,参数) method.setAccessible(true);//private函数 method.invoke(stu, null);//null表示无参数
|
1 2 3
| Student stu = (Student)classStu.newInstance(); Method method = classStu.getDeclaredMethod("habby", String.class);//参数类型 method.invoke(stu, "篮球");
|
注:在反射中,基本类型(int)和基本类型的包装类(Integer)是不同的类型
操作构造函数
1 2 3
| Constructor<?> constructor = classStu.getConstructor(null); Student stu = (Student)constructor.newInstance(); System.out.println(stu);
|
动态加载类名和方法
1 2
| classname=reflect.Student methodname=staticMethod
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Properties prop = new Properties(); prop.load(new FileReader("class.txt")); String classname = prop.getProperty("classname"); String methodname = prop.getProperty("methodname"); Class<?> classStu = null; //反射入口 try { classStu = Class.forName(classname); } catch (ClassNotFoundException e) { e.printStackTrace(); } Method method = classStu.getMethod(methodname); method.setAccessible(true); method.invoke(classStu.newInstance());
|
通过反射越过泛型检查
1 2 3 4 5 6 7 8 9
| ArrayList<Integer> list = new ArrayList(); list.add(123); list.add(22); Class<?> classStu = list.getClass(); Method method = classStu.getMethod("add", Object.class); method.invoke(list, "ssss"); System.out.println(list);
|
注:虽然可以通过反射访问等访问修饰符不允许访问的属性和方法,也可以忽略掉泛型检查,但不推荐使用,可能会引起程序的混乱
通过反射实现万能set方法
- obj:对象
- propertyName:属性名
- value:属性值
1 2 3 4 5 6 7 8
| public static void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Class<?> clazz = obj.getClass(); Field field = clazz.getDeclaredField(propertyName); field.setAccessible(true); field.set(obj, value); }
|
最后更新时间:
谢谢阅读本文,如果对文章或者网站有什么建议,请发邮件到:1799623289@qq.com