Java-Reflect 专题
基本反射简介:
1):JAVA 反射机制是在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法; 对于任意一个对象能够调用它的任意方法和属性; 这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制.
2):JAVA 反射 (放射) 机制:"程序运行时, 允许改变程序结构或变量类型, 这种语言称为动态语言". 从这个观看, Perl,PythonRuby 是动态语言, C++,Java,C# 不是动态语言.
3): 但是 JAVA 有着一个非常突出的动态相关机制: Reflection 用在 Java 身上指的是我们可以于运行时加载, 探知, 使用编译期间完全未知的 classes.
4): 换句话说, Java 程序可以加载一个运行时才得知名称的 class, 获悉其完整构造(但不包括 methods 定义), 并生成其对象实体, 或对其 fields 设值, 或唤起其 methods.
Java 反射机制提供的功能:
1): 在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象
2): 在运行时判断任意一个类所具有的成员变量和方法
3): 在运行时调用任意一个对象的方法
4): 生成动态代理
Class 类介绍:
Class 类描述 Java 程序运行时的所有 Classes 和 interfaces, 同时也用来描述 enum,array,Java 基本数据类型.
生成 Class: 当一个 class 文件被加载或者类加载器的 defineClass()被 JVM 调用时, JVM 便自动产生一个 Class 对象.
常用 API:
生成 Class 对象的方法:
1): 根据完整类名获取类, 调用 Class 的静态方法 forName():
Class<?> classType = Class.forName("java.lang.String");
2): 通过类名获取, 使用 class 语法, 这里 ReflectionTest 为一个类名:
Class<?> classType = ReflectionTest.class;
3): 通过对象的 getClass()方法获取:
- User user = new User();
- Class<?> classType = user.getClass();
- // 获取 user 的父类的 Class 对象
- Class superClass = classType.getSuperclass();
4): 对于包装类的 Class 的获取, 使用包装类的 TYPE 语法:
- Class classType = Integer.Type;
- Class c = Integer.class;
创建反射获取的类的实例的方法:
1): 调用 Class 的 newInstance()方法:
- Class c = Class.forName("mlq.Student");
- Student student = (Student) c.newInstance();
2): 通过 Class 获取构造方法再实例化:
- Class c = Class.forName("mlq.Student");
- Student student=(Student)c.getConstructor(new Class[]{
- }).newInstance(new Object[]{
- });
提示: 当 Class 数组为空时, 本质上等价于1, 即调用无参构造函数
获取方法信息函数:
1): 获取所有公共方法:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型, 获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
2): 获取所有方法:(不问访问权限)
Method getDeclaredMethod(String name, Class[] params) - 使用特写的参数类型, 获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获取的是所有该类自己声明的方法, 不问访问权限
获取成员变量:
1): 获取所有的 public 的成员变量的信息
Field getField(String name) -- 获得指定命名的公共字段
Field[] getFields()-- 方法获取的是所有的 public 的成员变量的信息
2): 获取所有成员变量:(不问访问权限)
Field getDeclaredField(String name) -- 获取指定的域, 返回一个 Field 对象, 该对象反映此 Class 对象所表示的类或接口的指定已声明字段:
Field[] getDeclaredFields()-- 获取所有的域, 包括公共, 保护, 默认 (包) 访问和私有域, 但不包括继承的域:
field.setAccessible(true);-- 设置压制访问控制检查, 这样就可以获取和设置私有域的值了:
Field field = classType.getDeclaredField("fieldName");-- 获取某个对象的域的对应值:
field.get(object);
Field field = classType.getDeclaredField("fieldName");-- 设置某个对象的域的对应值:
field.set(obj, "arthinking");
获取构造函数信息:
1): 获取所有 public 的函数:
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,
Constructor[] getConstructors()-- 获取所有的 public 的构造函数
2): 获取构造函数:(不问访问权限)
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)
Constructor[] getDeclaredConstructors()-- 得到自己声明的构造函数, 推荐使用(与接入级别无关)
案例 Demo: 点我下载源码
1): 获取 Student 类的完整限定名 ==》全类名
- /**
- * 获取 Student 类的完整限定名 ==》全类名
- * 01,Class.forName(类的完整限定名) 来加载类 (常用)
- * 02,Student.class 任何类名. class 都是获取了 Class 类
- * 03,new Student().getClass() 任何对象. getClass()都是获取了 Class 类
- */
- @Test
- public void test01() {
- try {
- System.out.println("打印类的完整限定名, 会走静态代码块:" + Class.forName("mlq.Student"));
- System.out.println("====================================");
- System.out.println("只打印类的全名称:" + Student.class);
- System.out.println("====================================");
- System.out.println("无参, 静态与非静态块, 类完整名称; 都会执行" + new Student().getClass().getName());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
2): 获取包名, 类名, 访问修饰符值 和 name
- /**
- * 获取包名, 类名, 访问修饰符值 和 name
- */
- @Test
- public void test02() {
- try {
- // 加载 Student 类
- Class c = Class.forName("mlq.Student");
- System.out.println("Student 所在包名称:" + c.getPackage().getName());
- System.out.println("Student 全类名:" + c.getName());
- System.out.println("Student 类名:" + c.getSimpleName());
- // 获取类的访问修饰符
- int num = c.getModifiers();
- System.out.println("public 访问修饰符对应的数值:" + num);
- // 访问修饰符对相应的名称
- System.out.println(Modifier.toString(num));
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
3): 获取类中所有的属性相关信息
- /**
- * 获取类中所有的属性相关信息
- */
- @Test
- public void test03() {
- try {
- Class c = Class.forName("mlq.Student");
- // 获取所有字段
- Field[] fields = c.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- System.out.println(fields[i]);
- }
- // 获取所有字段的访问修饰符
- for (int i = 0; i < fields.length; i++) {
- // 修饰符值对象的修饰符名称
- System.out.print(Modifier.toString(fields[i].getModifiers()));
- // 访问修饰符对应的数值
- System.out.println(":" + fields[i].getModifiers());
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
4): 获取类中所有的方法相关信息 不包含构造方法
- /**
- * 获取类中所有的方法相关信息 不包含构造方法
- * 01,c.getMethod(方法名称, 参数类型)只能是 public 修饰的
- * 02,c.getMethods()只能是 public 修饰的
- * 03,c.getDeclaredMethods() 所有
- */
- @Test
- public void test04() {
- try {
- Class c = Class.forName("mlq.Student");
- // 获取所有方法, 包含 private 私有的
- Method[] declaredMethods = c.getDeclaredMethods();
- for (int i = 0; i < declaredMethods.length; i++) {
- System.out.println("方法的名称是:" + declaredMethods[i].getName());
- System.out.println("方法的修饰符数值时:" + declaredMethods[i].getModifiers());
- System.out.println("方法的修饰符名称是:" + Modifier.toString(declaredMethods[i].getModifiers()));
- System.out.println("方法的返回值类型是:" + declaredMethods[i].getReturnType());
- System.out.println("=============================================");
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
5): 获取类中的所有构造方法相关信息
- /**
- * 获取类中的所有构造方法相关信息
- */
- @Test
- public void test05() {
- try {
- Class c = Class.forName("mlq.Student");
- // 获取所有构造, 包含 private 私有的
- Constructor[] declaredConstructors = c.getDeclaredConstructors();
- for (int i = 0; i < declaredConstructors.length; i++) {
- System.out.println("构造方法的名称是:" + declaredConstructors[i].getName());
- System.out.println("构造方法的修饰符数值是:" + declaredConstructors[i].getModifiers());
- System.out.print("构造的访问修饰符及参数列表:" + Modifier.toString(declaredConstructors[i].getModifiers()) + "(");
- // 获取构造中的参数
- Class[] parameterTypes = declaredConstructors[i].getParameterTypes();
- for (int j = 0; j < parameterTypes.length; j++) {
- System.out.print(parameterTypes[j].getName() + ",");
- }
- System.out.println(")");
- System.out.println("=======================================");
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
6): 访问类中私有的属性和方法并且让它执行
- /**
- * 访问类中私有的属性和方法并且让它执行
- */
- @Test
- public void test06() {
- try {
- Class c = Class.forName("mlq.Student");
- //Student student=(Student)c.getConstructor(new Class[]{}).newInstance(new Object[]{});
- // 实例化
- Student student = (Student) c.newInstance();
- // 获取私有字段
- Field userName = c.getDeclaredField("userName");
- // 输出字段名称
- System.out.println("输出字段名称:"+userName.getName());
- // 打开字段开关
- userName.setAccessible(true);
- //userName.set(student,"abc");
- // 输出字段信息
- System.out.println("输出字段信息:"+userName.get(student));
- // 获取私有的方法
- Method getSum = c.getDeclaredMethod("getSum", double.class);
- // 开启方法开关
- getSum.setAccessible(true);
- // 调用执行方法
- double invoke = (Double) getSum.invoke(student, 50.5);
- // 输出返回值
- System.out.println(invoke);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.
面对过去无怨无悔, 把握现在充满信心, 备战未来无所畏惧. 保持信念, 克服恐惧! 一点一滴的积累, 一点一滴的沉淀, 学技术需要不断的积淀!
来源: https://www.cnblogs.com/mlq2017/p/10049441.html