Skip to content
On this page

Access Fields

For any Object instance, as long as we obtain its Class , we can obtain all its information.

Let's first look at how to obtain field information through Class instances. The Class class provides the following methods to obtain fields:

  • Field getField(name): Get a public field (including parent class) based on the field name
  • Field getDeclaredField(name): Get a field of the current class based on the field name (excluding the parent class)
  • Field[] getFields(): Get all public fields (including parent classes)
  • Field[] getDeclaredFields(): Get all fields of the current class (excluding parent classes)

Let's take a look at the sample code:

java
// reflection
public class Main {
  public static void main(String[] args) throws Exception {
    Class stdClass = Student.class;
    // Get the public field "score":
    System.out.println(stdClass.getField("score"));
    // Get the inherited public field "name":
    System.out.println(stdClass.getField("name"));
    // Get the private field "grade":
    System.out.println(stdClass.getDeclaredField("grade"));
  }
}

class Student extends Person {
  public int score;
  private int grade;
}

class Person {
  public String name;
}

The above code first obtains Student 's Class instance, and then obtains public field, inherited public field, and private field respectively. The printed Field is similar:

public int Student.score
public java.lang.String Person.name
private int Student.grade

A Field object contains all the information of a field:

  • getName() : Returns the field name, for example, "name" ;
  • getType() : Returns the field type, which is also a Class instance, for example, String.class ;
  • getModifiers() : Returns the modifiers of the field, which is an int . Different bits represent different meanings.

Taking the value field of the String class as an example, its definition is:

java
public final class String {
    private final byte[] value;
}

We use reflection to obtain the information of this field. The code is as follows:

java
Field f = String.class.getDeclaredField("value");
f.getName(); // "value"
f.getType(); // class [B represents byte[] type
int m = f.getModifiers();
Modifier.isFinal(m); // true
Modifier.isPublic(m); // false
Modifier.isProtected(m); // false
Modifier.isPrivate(m); // true
Modifier.isStatic(m); // false

Get field value

Using reflection to get a Field instance of the field is only the first step. We can also get the value of the field corresponding to an instance.

For example, for a Person instance, we can first get Field corresponding to name field, and then get the value of name field of this instance:

java
// reflection
import java.lang.reflect.Field;
public class Main {

    public static void main(String[] args) throws Exception {
        Object p = new Person("Xiao Ming");
        Class c = p.getClass();
        Field f = c.getDeclaredField("name");
        Object value = f.get(p);
        System.out.println(value); // "Xiao Ming"
    }
}

class Person {
    private String name;

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

The above code first obtains Class instance, then Field instance, and then uses Field.get(Object) to obtain the value of the specified field of the specified instance.

Run the code, and if nothing goes wrong, you will get an IllegalAccessException . This is because name is defined as a private field. Under normal circumstances, the Main class cannot access private field of Person class. To fix the error, you can change private to public , or write a sentence before calling Object value = f.get(p);

java
f.setAccessible(true);

Calling Field.setAccessible(true) means that access is allowed regardless of whether the field is public or not.

You can try adding the above statement and then running the code to print out the value of the private field.

Some children may ask: If reflection can be used to obtain the value of a private field, then what is the meaning of class encapsulation?

The answer is that under normal circumstances, we always access Person 's name field through p.name . The compiler will decide whether to allow access to the field based on public , protected and private , thus achieving the purpose of data encapsulation.

Reflection is an unconventional usage. When using reflection, first of all, the code is very cumbersome. Secondly, it is more used by tools or underlying frameworks. The purpose is to obtain specific fields without knowing any information about the target instance. value.

Additionally, setAccessible(true) may fail. If SecurityManager exists during the JVM runtime, it will be checked according to the rules and may prevent setAccessible(true) . For example, a SecurityManager may not allow calling setAccessible(true) on package classes starting with java and javax , which can ensure the security of the JVM core library.

Set field value

Since the field value of the specified instance can be obtained through the Field instance, naturally the field value can also be set.

Setting the field value is implemented through Field.set(Object, Object) , where the first Object parameter is the specified instance, and the second Object parameter is the value to be modified. The sample code is as follows:

java
// reflection
import java.lang.reflect.Field;

public class Main {

    public static void main(String[] args) throws Exception {
        Person p = new Person("Xiao Ming");
        System.out.println(p.getName()); // "Xiao Ming"
        Class c = p.getClass();
        Field f = c.getDeclaredField("name");
        f.setAccessible(true);
        f.set(p, "Xiao Hong");
        System.out.println(p.getName()); // "Xiao Hong"
    }
}

class Person {
    private String name;

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

    public String getName() {
        return this.name;
    }
}

After running the above code, the printed name field changes from Xiao Ming to Xiao Hong , indicating that the value of the field can be directly modified through reflection.

Similarly, to modify non-public fields, you need to call setAccessible(true) first.

Summary

Field class provided by Java's reflection API encapsulates all information about the field:

Field instances can be obtained through the methods of Class instances: getField() , getFields() , getDeclaredField() , getDeclaredFields() ;

Field information can be obtained through Field instances: getName() , getType() , getModifiers() ;

Fields of an object can be read or set through Field instances. If there are access restrictions, setAccessible(true) must be called first to access non-public fields.

Reading and writing fields via reflection is an unconventional approach that breaks the object's encapsulation.

Access Fields has loaded