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

反射、反射调用以及修改成员变量,成员方法,构造函数、反射的应用

DAY11.2 Java核心基础

反射(第二弹)

第一弹请访问链接:

反射(第一篇)

  • getMethod(String name, Class… parameterTypes)
  • getMethods()
  • getDeclaredMethod(String name,Class… parameterTypes)
  • getDeclaredMethods()

getMethods() 获取类中所有方法,包括从父类继承过来的方法以及自定义的方法,这些方法都是 public 方法

public String getName() {
    return name;
}

private void setName(String name) {
    this.name = name;
}

protected int getAge() {
    return age;
}

void setAge(int age) {
    this.age = age;
}

@Override
public String toString() {
    return "User{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
    Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
    Method[] methods = class1.getMethods();
    for (Method method : methods) {
        System.out.println(method.getName());
    }
}

image-20250314114226045

可以看见这个输出只有public访问符的方法

getMethod(String name,Class… parameterTypes) 根据方法名和参数列表获取具体的某个方法,只能是 public

方法,包括自定义的方法以及从父类继承过来的方法

private void setName(String name) {
    this.name = name;
}
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Method setName = class1.getMethod("setName", String.class);
System.out.println(setName);

image-20250314114615886

这样是获取不到的,抛出找不到方法的异常

因为这个只能获取到公有方法(public修饰的)

改为public就可以获取到了

image-20250314114717350

同理

getDeclaredMethods() 获取类中所有的方法,包括 public、protected、private、默认,但是无法获取从父类继承过来的方法

public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
    Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
    Method[] declaredMethods = class1.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {
        System.out.println(declaredMethod.getName());
    }
}
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

protected int getAge() {
    return age;
}

void setAge(int age) {
    this.age = age;
}

@Override
public String toString() {
    return "User{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}

输出:

image-20250314114947797

可以看见可以获取所有声明的方法,和这个方法的访问权限符无关

getDeclaredMethod(String name,Class… parameterTypes) 根据方法名和参数列表获取具体的某个方法,对于访问权限修饰符没有限制,但是只能获取自定义的方法

Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Method getAge = class1.getDeclaredMethod("getAge");
System.out.println(getAge);

获取到的是protected的方法,对于访问权限修饰符没有限制,但是只能获取自定义的方法

image-20250314115329416

获取类中成员变量

Class 提供了 4 个方法获取类中的成员变量

  • getFields():获取类中全部的 public 修饰的成员变量,包括继承自父类的成员变量以及自定义的成员变量
  • getDeclaredFields():获取类中全部修饰符修饰的成员变量,但仅限于类自定义的,不包括从父类继承过来的
  • getField(String name):根据成员变量名称获取类中的某个具体的 public 修饰的成员变量,包括继承自父类的成员变量以及自定义的成员变量
  • getDeclaredField(String name):根据成员变量名称获取类中某个具体的成员变量,不受访问权限修饰符的限制,但是只能获取类自定义的成员变量,不包括从父类继承过来的成员变量

和上面的获取方法同理

类中的字段:

public String name;
public int age;
private String sex;
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Field[] fields = class1.getFields();
for (Field field : fields) {
    System.out.println(field);
}
System.out.println(class1.getDeclaredField("name"));

image-20250314115853375

可以看见getFields()获取到两个public的字段,getDeclaredField获取的是privare的sex

反射就是在程序运行的时候动态获取类的信息(比如构造器,成员方法,成员变量)

反射的应用

通过 Class 类提供的方法可以获取类中的成员变量、成员方法、构造函数

获取这些有什么用?实际开发中如何应用反射?

反射调用方法

常规创建并操作对象的方法

public User(String name, int age, String sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
public String getInfo() {
    return this.name + " " + this.age + " " + this.sex;
}
User user = new User("deepseek", 18, "男");
user.getInfo();

User类的构造方法和测试方法

getMethod() 和 invoke()

public User(String name, int age, String sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
public String getInfo() {
    return this.name + " " + this.age + " " + this.sex;
}
Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Constructor constructor = class1.getConstructor(String.class, int.class, String.class);
User user1 = (User) constructor.newInstance("deepSeek", 18, "男");
Method getInfoMethod = class1.getMethod("getInfo",null);
System.out.println(getInfoMethod.invoke(user1));

输出:

image-20250314151315980

反射就是将常规方式进行反转

// 常规调用
user.getInfo();
// 反射创建
Method getInfoMethod = class1.getMethod("getInfo",null);
System.out.println(getInfoMethod.invoke(user1));

常规:

1、创建实例化对象

2、调用实例化对象的方法

反射:

1、获取反射源头 Class 对象

2、根据 Class 对象获取目标方法

3、通过反射机制调用目标方法

反射访问成员变量

getDeclaredFields() :获取类中所有成员变量

Class class1 = Class.forName("com.deepSeek.shuwu.Day11.User");
Field[] declaredFields = class1.getDeclaredFields();
for (Field declaredField : declaredFields) {
    // 获取字段名称、类型、修饰符、泛型类型
    System.out.println(declaredField.getName());
    System.out.println(declaredField.getType());
    System.out.println(declaredField.getModifiers());
    System.out.println(declaredField.getGenericType());
    System.out.println("-------------------------------");
}

image-20250314153500517

获取字段,然后可以传入对象获取对象的id;

public static void main(String[] args) throws Exception {
    // 加载 User 类
    Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");

    // 创建 User 对象
    User user1 = new User("user1", 18, "男");
    User user2 = new User("user2", 18, "男");
    User user3 = new User("user3", 18, "男");

    // 获取 name 字段(假设它是 public 的)
    Field name = class1.getField("name");
    System.out.println(name.get(user1)); 
    System.out.println(name.get(user2)); 
    System.out.println(name.get(user3)); 

    // 获取 sex 字段(private 字段)
    Field sex = class1.getDeclaredField("sex");
    sex.setAccessible(true); 
    System.out.println(sex.get(user1)); 

    // 修改 user1 的 sex 字段值
    sex.set(user1, "女");
    System.out.println(sex.get(user1)); 
}

输出:

image-20250314165842249

可以通过反射获取到对象的private值,以及对对象的值进行修改

如下图所示:

image-20250314170801136

反射调用构造函数

反射机制下用 Constructor 类来描述构造函数,同时一个类可以拥有多个构造函数

一个User类中的三个构造函数:

public User(String name, int age, String sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
public User() {
    
}
public User(String name, int age) {
    this.name = name;
    this.age = age;
}
@Override
public String toString() {
     eturn "User{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", sex='" + sex + '\'' +
            '}';
}

测试类;

// 加载 User 类
Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");

Constructor<?> constructor1 = class1.getConstructor(String.class, int.class);
User user1 = (User) constructor1.newInstance("李四", 20);
System.out.println(user1);

Constructor<?> constructor2 = class1.getConstructor(null);
User user2 = (User) constructor2.newInstance();
System.out.println(user2);

Constructor<?> constructor3 = class1.getConstructor(String.class, int.class, String.class);
User user3 = (User) constructor3.newInstance("张三", 18, "男");
System.out.println(user3);

输出:

image-20250314171428240

反射调用构造函数和反射调用普通方法的区别

1、构造函数使用 Constructor 来表示,普通方法使用 Method 来表示

2、Constructor 调用的是 newInstance 方法,Method 调用的是 invoke 方法

3、Constructor 不需要传入对象,只需传入参数,Method 需要同时传入对象和参数

直接访问成员变量进行赋值 or 通过调用成员方法对成员变量进行赋值

public static void main(String[] args) throws Exception {
    // 加载 User 类
    Class<?> class1 = Class.forName("com.deepSeek.shuwu.Day11.User");

    User user =new User();
    Field name = class1.getField("name");
    // 直接赋值
    name.set(user,"deepSeek");
    
    // 如果不是public字段,需要先设置可访问性
    Field age = class1.getDeclaredField("age");
    age.setAccessible(true);
    age.set(user,19);
    
    // 调用 setSex 方法赋值,前提是这个方法是public
    Method setSex = class1.getMethod("setSex", String.class);
    setSex.invoke(user,"女");
    // 输出
    System.out.println(user);
}

image-20250314172810633


http://www.kler.cn/a/586587.html

相关文章:

  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_11多功能组合的固定表头表格
  • 绿色高效运维:分布式光伏监控系统的全生命周期管理
  • 文件系统 linux ─── 第19课
  • 新手村:统计量均值、中位数、标准差、四分位数
  • 将pdf或者word转换成base64格式
  • 通达信软件+条件选股+code
  • 如何在github上参与开源项目
  • Java基础语法练习43(线程)
  • 网络实验操作-VLAN
  • lws-minimal-ws-server前端分析
  • 考研数学复习误区:如何避免无效学习?
  • 3.4 基于TSX的渲染函数类型安全实践
  • Julia语言的饼图
  • Java常见的几种内存溢出及解决方法
  • BSides-Vancouver-2018 ftp匿名访问、hydra爆破22端口、nc瑞士军刀、提权
  • C++类对象创建全解析:从构造函数到内存管理
  • SQL Server语法实战指南:核心语法、注意事项与高频问题解析
  • Java基础-List、Set、Map
  • MATLAB中enumeration函数用法
  • 【FPGA实战】Verilog实现DE2-115的流水灯控制