当前位置: 首页 > news >正文

Java高级-04.反射-获取成员变量和方法对象并使用

一.获取类的成员变量 

package com.njau.d2_reflect;public class Cat {public static int a;public static final String COUNTRY = "中国";private String name;private int age;public Cat(String name, int age) {System.out.println("有参数构造器执行了!");this.name = name;this.age = age;}public Cat() {System.out.println("无参构造器执行了!");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +'}';}
}

 * public Field[] getFields()   获取类的全部成员变量(只能获取public修饰的)
 * public Field[] getDeclaredFields()  获取类的全部成员变量(只要存在就能拿到)
 * public Field getField()   获取类的某个成员变量(只能获取public修饰的)
 * public Field getDeclaredField()  获取类的全部成员变量(只要存在就能拿到)

返回回来的是一个Filed类型的对象。可以使用数组接收多个。

package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Field;/*** 目标:掌握获取类的成员变量* Class提供了从类中获取成员变量的方法* public Field[] getFields()   获取类的全部成员变量(只能获取public修饰的)* public Field[] getDeclaredFields()  获取类的全部成员变量(只要存在就能拿到)* public Field getField(String name)   获取类的某个成员变量(只能获取public修饰的)* public Field getDeclaredField(String name)  获取类的全部成员变量(只要存在就能拿到)* 获取到成员变量的作用:依然是赋值,取值* void set(Object obj,Object value)   赋值* Object get(Object obj)   取值* public void setAccessible(boolean flag)   设置为true,表示禁止检查访问控制(暴力反射)*/public class Test3Field {@Testpublic void testGetFields() throws Exception {// 1、反射第一步:首先获取到类Class对象Class c = Cat.class;// 2、public Field[] getFields()   获取类的全部成员变量(只能获取public修饰的)
//        Field[] fields = c.getFields();Field[] fields = c.getDeclaredFields();    // 获取类的全部成员变量(只要存在就能拿到)for (Field field : fields) {System.out.println(field.getName() + "--->" + field.getType());}// 3、public Field getField(String name)   获取类的某个成员变量(只能获取public修饰的)Field fName = c.getDeclaredField("name");System.out.println(fName.getName() + "--->" + fName.getType());    // name--->class java.lang.String// 4、public Field getDeclaredField(String name)  获取类的某个成员变量(只要存在就能拿到)Field fAge = c.getDeclaredField("age");System.out.println(fAge.getName() + "--->" + fAge.getType());   // age--->int}
}

 获取成员变量的作用:依然是赋值、取值

使用set进行赋值,但是赋值时必须要创建出该类的实例化对象,否则这个值又赋给谁呢?同样的,使用get方法时也要传入该类的实例化对象,否则不知道获取哪个对象的成员变量值。

注意:我们在获得构造器和成员变量的时候均不用setAccessible方法,而是在使用构造器实例化对象和使用成员变量赋值的时候,对于私有的构造器和成员变量才要使用setAccessible方法。成员方法也和上述一样。

package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Field;/*** 目标:掌握获取类的成员变量* Class提供了从类中获取成员变量的方法* public Field[] getFields()   获取类的全部成员变量(只能获取public修饰的)* public Field[] getDeclaredFields()  获取类的全部成员变量(只要存在就能拿到)* public Field getField()   获取类的某个成员变量(只能获取public修饰的)* public Field getDeclaredField()  获取类的全部成员变量(只要存在就能拿到)* 获取到成员变量的作用:依然是赋值,取值* void set(Object obj,Object value)   赋值* Object get(Object obj)   取值* public void setAccessible(boolean flag)   设置为true,表示禁止检查访问控制(暴力反射)*/public class Test3Field {@Testpublic void testGetFields() throws Exception {// 1、反射第一步:首先获取到类Class对象Class c = Cat.class;// 2、public Field[] getFields()   获取类的全部成员变量(只能获取public修饰的)
//        Field[] fields = c.getFields();Field[] fields = c.getDeclaredFields();    // 获取类的全部成员变量(只要存在就能拿到)for (Field field : fields) {System.out.println(field.getName() + "--->" + field.getType());}// 3、public Field getField(String name)   获取类的某个成员变量(只能获取public修饰的)Field fName = c.getDeclaredField("name");System.out.println(fName.getName() + "--->" + fName.getType());    // name--->class java.lang.String// 4、public Field getDeclaredField(String name)  获取类的某个成员变量(只要存在就能拿到)Field fAge = c.getDeclaredField("age");System.out.println(fAge.getName() + "--->" + fAge.getType());   // age--->int}@Testpublic void testSetAndGet() throws Exception {Class c = Cat.class;Cat cat = new Cat();
//        获取某个类的成员变量Field fName = c.getDeclaredField("name");
//        public void setAccessible(boolean flag)   设置为true,表示禁止检查访问控制(暴力反射)fName.setAccessible(true);   // 禁止访问控制权限
//        void set(Object obj,Object value)   赋值fName.set(cat, "招财猫");
//        Object get(Object obj)   取值String name = (String) fName.get(cat);System.out.println(name);System.out.println(cat);Field fAge = c.getDeclaredField("age");
//        public void setAccessible(boolean flag)   设置为true,表示禁止检查访问控制(暴力反射)fAge.setAccessible(true);
//        void set(Object obj,Object value)   赋值fAge.set(cat,3);
//        Object get(Object obj)   取值int age = (int) fAge.get(cat);System.out.println(age);System.out.println(cat);}
}

调用get方法时并不知道返回的成员变量类型,因此java官方为我们设定了Object类型。但是我们要将其进行强制转换。

二.获取类的成员方法 

package com.njau.d2_reflect;public class Cat {public static int a;public static final String COUNTRY = "中国";private String name;private int age;public Cat(String name, int age) {System.out.println("有参数构造器执行了!");this.name = name;this.age = age;}public Cat() {System.out.println("无参构造器执行了!");}public String getName() {return name;}private void run() {System.out.println("🐱跑的贼快~~");}public void eat() {System.out.println("🐱爱吃猫粮~~");}// 方法的重载private String eat(String name) {return "🐱爱吃" + name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +'}';}
}

 * Method[] getMethods()   获取类的全部成员方法(只能获取public修饰的)
 * Method[] getDeclaredMethods()   获取类的全部成员方法(只要存在就能获取)
 * Method[] getMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只能获取public修饰的)
 * Method[] getDeclaredMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只要存在就能获取)

首先我们要获取类的成员方法,就要先获取类对象。因此反射的第一步永远都是获取类对象。

package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Method;/*** 目标:获取类的成员方法* Method[] getMethods()   获取类的全部成员方法(只能获取public修饰的)* Method[] getDeclaredMethods()   获取类的全部成员方法(只要存在就能获取)* Method[] getMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只能获取public修饰的)* Method[] getDeclaredMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只要存在就能获取)* 成员方法的作用:依然是执行* public Object invoke(Object obj, Object ... args)   出发某个对象的该方法执行  Object obj代表类的某个实例对象* public void setAccessible(boolean flag)  设置为true,表示禁止检查访问控制(暴力反射)*/
public class Test4Method {@Testpublic void testGetDeclaredMethods() throws Exception {// 1、反射第一步:首先获取Class对象Class c = Cat.class;// 2、获取类的全部成员方法Method[] methods = c.getDeclaredMethods();// 3、对所有成员方法进行遍历for (Method method : methods) {System.out.println(method.getName() + "--->" + method.getParameterCount()+ "--->" + method.getReturnType());}// 4、获得某个成员方法Method run = c.getDeclaredMethod("run");System.out.println(run.getName() + "--->" + run.getParameterCount()+ "--->" + run.getReturnType());  // run--->0--->voidMethod eat = c.getDeclaredMethod("eat",String.class);System.out.println(eat.getName() + "--->" + eat.getParameterCount()+ "--->" + eat.getReturnType());  // eat--->1--->class java.lang.String}
}

我们使用getDeclaredMethods()方法来获取类中的全部实例对象。然后用Method类型的数据对其进行封装。封装后我们进行遍历,在遍历时我们可以使用:

1.getName()方法获得该方法的方法名

2.getParameterCount()方法获得该方法的参数个数

3.getReturnType()方法获得该方法的返回值类型

我们使用getDeclaredMethod(String name,Class<?> ... parameterTypes)方法来获取类中的指定的实例对象。其中要获得指定的方法吗,就要在name字段指定方法名,在Class<?> ... parameterTypes字段指定参数类型。

通过反射获得成员方法的作用依然是执行 

 * public Object invoke(Object obj, Object ... args)   出发某个对象的该方法执行  Object obj代表类的某个实例对象
 * public void setAccessible(boolean flag)  设置为true,表示禁止检查访问控制(暴力反射)

我们可以在获得成员方法对象后通过invoke方法执行该成员方法。但是在使用invoke方法之前,我们首先要new一个该方法所在类的实例化对象,因为这个成员方法是该类的成员方法,是通过该类的实例化对象进行调用的。因此要先将该类实例化对象出来,再将该对象传入invoke方法里才能够进行调用。

package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Method;/*** 目标:获取类的成员方法* Method[] getMethods()   获取类的全部成员方法(只能获取public修饰的)* Method[] getDeclaredMethods()   获取类的全部成员方法(只要存在就能获取)* Method[] getMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只能获取public修饰的)* Method[] getDeclaredMethod(String name,Class<?> ... parameterTypes)   获取类的某个成员方法(只要存在就能获取)* 成员方法的作用:依然是执行* public Object invoke(Object obj, Object ... args)   出发某个对象的该方法执行  Object obj代表类的某个实例对象* public void setAccessible(boolean flag)  设置为true,表示禁止检查访问控制(暴力反射)*/
public class Test4Method {@Testpublic void testGetDeclaredMethods() throws Exception {// 1、反射第一步:首先获取Class对象Class c = Cat.class;// 2、获取类的全部成员方法Method[] methods = c.getDeclaredMethods();// 3、对所有成员方法进行遍历for (Method method : methods) {System.out.println(method.getName() + "--->" + method.getParameterCount()+ "--->" + method.getReturnType());}// 4、获得某个成员方法Method run = c.getDeclaredMethod("run");System.out.println(run.getName() + "--->" + run.getParameterCount()+ "--->" + run.getReturnType());  // run--->0--->voidMethod eat = c.getDeclaredMethod("eat",String.class);System.out.println(eat.getName() + "--->" + eat.getParameterCount()+ "--->" + eat.getReturnType());  // eat--->1--->class java.lang.StringCat cat = new Cat();  // 创建一个猫对象run.setAccessible(true);   // 表示禁止检查访问控制(暴力反射)Object object = run.invoke(cat);  // 🐱跑的贼快~~System.out.println(object);  // null  没有返回值,就是nulleat.setAccessible(true);String food = (String) eat.invoke(cat, "鱼儿");System.out.println(food);}
}

我们使用获取到的成员方法对象run调用invoke方法执行run方法,在调用invoke方法前我们实例化一个Cat类对象cat,并将该对象传入invoke方法中,又因为run方法没有参数,因此不需要传递参数。也没有返回值,因此返回值为null。java官方并不知道我们的方法返回值类型是什么,因此统一使用Object进行接收。

同样的,在调用eat的重载方法时,有一个参数String类型的,因此要传入一个字符串。且返回值是一个字符串,因此要使用String类型的变量接收并打印出来。

当我们在调用invoke进行方法的执行时,由于我们的方法在定义时都是用private修饰的,因此再调用invoke执行该方法时会出现权限不够,因此要使用setAccessible()方法将其设置为true。才能保证正常执行。

执行结果: 


http://www.mrgr.cn/news/94444.html

相关文章:

  • QT中读取QSetting文件
  • Android 高版本 DownloadManager 封装工具类,支持 APK 断点续传与自动安装
  • C++ primer plus 类和对象下
  • VSCode C/C++ 开发环境完整配置及常见问题(自用)
  • 神经网络中常用语言特性(python)(待完善)
  • 软考计算机知识-流水线
  • 【AWS入门】2025 AWS亚马逊云科技账户注册指南
  • 解释VLA和具身智能之间的关系
  • 插入排序算法的SIMD优化
  • JavaScript基础篇:六、 函数基础
  • 模版题目的集合
  • 《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成
  • Machine Learning: 十大基本机器学习算法
  • 【春招笔试】2025.03.12-小米春招笔试
  • MySQL -- 表的约束
  • 数据结构概览
  • 云服务器新手配置内网穿透服务(frp)
  • steam 赛题
  • JavaScript基础篇:四、 运算符与表达式
  • c语言笔记 字符串函数---strstr strlen strtok以及sizeof