有问有答—JavaSE—反射应用

写一个函数,传入任意的对象,可以将对象里面String类型的属性中的a改成b。

field.getClass()

private void changeField(Object object) throws IllegalAccessException {
    //1.获得对应的字节码
    Class clazz = object.getClass();//对象.getClass。  类.class
    //2.获取所有的fields
    Field[] fields = clazz.getDeclaredFields();//所有的  包括私有的
    //3.遍历所有的field,如果是String类型,将包含a改为b
    for (Field field : fields) {
        //3.1 是String类型才修改
        if (field.getType() == String.class) {
            //属性是私有的
            field.setAccessible(true);
            //person.getName()
            //3.2 获得field原来的值
            String oldValue = (String) field.get(object);
            if (oldValue == null || "".equals(oldValue)) {
                continue;
            }
            String newValue = oldValue.replace("a", "b");
            //3.3 将修改后的值设置到field
            //person.setName("11");
            field.set(object, newValue);
        }
    }
}

1 能不能用field.class == String.class来判断类型是否相等?

在 Java 中,使用 field.getType() == String.class 来判断字段的类型是否为 String 是正确的做法,而 field.class == String.class 则是错误的。原因在于 field 是一个 Field 对象,而不是一个类。field.class 指向的是 Field 类的字节码对象,而不是字段本身的类型。

正确的类型判断方法

要判断字段的类型是否为 String,应该使用 field.getType() 方法。field.getType() 返回的是一个 Class 对象(压根不能这样写),表示该字段的类型。

正确的代码示例
private void changeField(Object object) throws IllegalAccessException {
    // 1.获得对应的字节码
    Class<?> clazz = object.getClass(); // 使用对象.getClass 获取类对象
    // 2.获取所有的 fields
    Field[] fields = clazz.getDeclaredFields(); // 获取所有的字段,包括私有字段
    // 3.遍历所有的 field,如果是 String 类型,将包含 a 改为 b
    for (Field field : fields) {
        // 3.1 是 String 类型才修改
        if (field.getType() == String.class) { // 正确的类型判断方法
            // 属性是私有的
            field.setAccessible(true);
            // 获取字段的当前值
            String oldValue = (String) field.get(object);
            if (oldValue != null) { // 确保旧值不是 null
                String newValue = oldValue.replace("a", "b");
                // 将修改后的值设置到字段
                field.set(object, newValue);
            }
        }
    }
}

解释

  • field.getType() == String.class:这是正确的判断方法。field.getType() 返回字段的类型 Class 对象,通过比较它与 String.class,可以判断该字段是否是 String 类型。
  • field.class == String.class:这是错误的,因为 field 是一个 Field 对象,而 field.class 指向的是 Field 类的字节码对象,而不是字段的类型。

其他注意事项

  1. 检查旧值是否为 null
    在使用 oldValue.replace("a", "b") 之前,应该检查 oldValue 是否为 null,以避免 NullPointerException

  2. 设置字段的可访问性
    使用 field.setAccessible(true) 来访问私有字段。完成后,最好将其恢复为不可访问状态(可选)。

  3. 异常处理
    确保捕获和处理所有可能的异常,尤其是在反射操作中。

总结

在反射操作中,判断字段类型应该使用 field.getType() == String.class。直接比较 field.classString.class 是不正确的,因为 fieldField 类的实例,而不是表示字段的类型。通过正确的方法,可以有效地操作对象的字段,实现所需的功能。

2 field.getClass行不行?

field.getClass() 不能用于判断字段的类型是否为 String。让我们更详细地解释原因并提供适当的方法。

详细解释

  • field.getClass()

    • field 是一个 Field 对象,因此 field.getClass() 返回的是 Field 类的 Class 对象。这并不是字段的类型,而是 Field 类本身的类型。
    • 换句话说,field.getClass() 始终返回的是 Field.class,无论该 Field 对象表示的是 String 类型的字段还是其他类型的字段。
  • field.getType()

    • field.getType() 返回的是这个字段的类型。例如,如果字段是 String 类型,则 field.getType() 返回 String.class

示例代码和比较

错误的用法
if (field.getClass() == String.class) {
    // 这段代码永远不会为 true,因为 field.getClass() 返回的是 Field.class
}
正确的用法
if (field.getType() == String.class) {
    // 这段代码会在字段类型为 String 时为 true
}

完整示例

以下是如何正确判断字段是否为 String 类型的完整代码示例:

import java.lang.reflect.Field;

public class ReflectDemo {
    public static void main(String[] args) throws IllegalAccessException {
        Student student = new Student();
        student.setName("aName");
        student.setAge(20);
        
        changeField(student);
        System.out.println("Updated student: " + student);
    }

    private static void changeField(Object object) throws IllegalAccessException {
        // 1.获得对应的字节码
        Class<?> clazz = object.getClass();
        // 2.获取所有的 fields
        Field[] fields = clazz.getDeclaredFields();
        // 3.遍历所有的 field,如果是 String 类型,将包含 a 改为 b
        for (Field field : fields) {
            // 3.1 是 String 类型才修改
            if (field.getType() == String.class) { // 正确的类型判断方法
                // 属性是私有的
                field.setAccessible(true);
                // 获取字段的当前值
                String oldValue = (String) field.get(object);
                if (oldValue != null) { // 确保旧值不是 null
                    String newValue = oldValue.replace("a", "b");
                    // 将修改后的值设置到字段
                    field.set(object, newValue);
                }
            }
        }
    }

    static class Student {
        private String name;
        private int age;

        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;
        }

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

关键点

  • field.getClass():返回 Field 对象的类,即 Field.class,无法用于判断字段的类型。
  • field.getType():返回字段的实际类型,可以用于判断字段是否为 String 类型。

通过使用 field.getType(),可以正确地判断字段的类型并实现所需的逻辑操作。

3 .class和.getClass()的测试

package com.sdust.day37;

public class Teacher {
    private String name = "android";
    private int age = 18;
    private String address = "qingdao";

    @Override
    public String toString() {
        return "Teacher [name=" + name + ", age=" + age + ", address="
                + address + "]";
    }
}
@Test
public void testPointClass() {
    System.out.println(String.class);
    System.out.println("----------------------");
    Class clazz = Teacher.class;
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        System.out.println(field.getClass());
        System.out.println(field.getType());
    }
}
class java.lang.String
----------------------
class java.lang.reflect.Field
class java.lang.String

class java.lang.reflect.Field
int

class java.lang.reflect.Field
class java.lang.String
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值