Java反射 获取/修改字段

在Java反射中,可以使用Field类来获取和设置类的字段。字段可以是类变量(静态字段)或实例变量。可以使用getField()和getDeclaredField()方法来获取特定字段的值,然后使用set()方法来修改字段的值。以下是更详细的解释和示例代码。

首先,使用Class类的getField()和getDeclaredField()方法获取字段。其中,getField()方法只能获取公共的类变量(静态变量),而getDeclaredField()方法则可以获取所有字段,包括私有和受保护的变量。以下是获取字段的示例代码:

public class Person {
    public String name;
    protected int age;
    private String gender;
}

public class Main {
    public static void main(String[] args) throws Exception {
        // 获取所有字段
        Field[] fields = Person.class.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        // 获取指定的字段
        Field field = Person.class.getDeclaredField("name");
        System.out.println(field);
    }
}

输出结果为:
public java.lang.String Person.name
protected int Person.age
private java.lang.String Person.gender
public java.lang.String Person.name

接下来,可以使用Field对象的get()方法来获取字段的值,并使用set()方法来设置字段的值。以下是示例代码:

public class Person {
    public String name;
    protected int age;
    private String gender;

    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Person person = new Person("John", 25, "male");

        // 获取指定的字段
        Field field = Person.class.getDeclaredField("name");

        // 获取字段的值
        String name = (String) field.get(person);
        System.out.println("Name: " + name);

        // 设置字段的值
        field.set(person, "Alice");
        System.out.println("Name: " + person.name);
    }
}

输出结果为:
Name: John
Name: Alice

在上面的示例代码中,首先使用get()方法获取person对象的name字段的值,并将其转换为String类型。然后使用set()方法将person对象的name字段的值设置为”Alice”。最后再次输出person对象的name字段的值,确认字段的值已经被修改。

需要注意的是,如果字段是私有的,则需要使用setAccessible(true)方法打开访问控制,否则会抛出IllegalAccessException异常。以下是修改私有字段的示例代码:

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    private void sayHello() {
        System.out.println("Hello, " + name);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Person person = new Person("John");

        // 获取私有字段
        Field field = Person.class.getDeclaredField("name");

        String name = (String) field.get(person);
        System.out.println("Name: " + name);

        }
}

输出结果为:
Name: John

获取和修改方法的示例代码如下:

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // 创建对象
        Class<Person> personClass = Person.class;
        Person person = personClass.getConstructor(String.class, int.class).newInstance("Alice", 25);

        // 获取和修改字段
        Field nameField = personClass.getDeclaredField("name");
        nameField.setAccessible(true); // 必须先将访问标志设置为 true
        System.out.println("Before modification, name is " + nameField.get(person));
        nameField.set(person, "Bob");
        System.out.println("After modification, name is " + nameField.get(person));

        // 获取和调用方法
        Method sayHelloMethod = personClass.getDeclaredMethod("sayHello");
        sayHelloMethod.invoke(person);
    }
}

输出结果如下:
Before modification, name is Alice
After modification, name is Bob
Hello, my name is Bob and I am 25 years old.

在上面的代码中,我们首先使用 getDeclaredField() 方法获取了 Person 类中的 name 字段,并将其访问标志设置为 true,以允许我们访问私有字段。然后我们使用 get() 和 set() 方法分别获取和修改字段的值。

接下来,我们使用 getDeclaredMethod() 方法获取了 Person 类中的 sayHello() 方法,然后使用 invoke() 方法调用该方法。

需要注意的是,如果要访问私有方法或字段,必须先将其访问标志设置为 true。同时,在使用 getDeclaredField() 和 getDeclaredMethod() 方法时,需要传入字段或方法的名称作为参数。如果要获取所有的字段或方法,可以使用 getDeclaredFields() 和 getDeclaredMethods() 方法。

以上就是使用反射获取和修改字段、调用方法的示例。需要注意的是,在实际开发中,应尽量避免使用反射,因为它会降低代码的可读性和可维护性。