1. Introduction
In this tutorial, we’ll learn how to get a String value from a Java field using reflection. Reflection in Java is a powerful feature that allows us to inspect and interact with classes, fields, methods, and constructors at runtime, even if we don’t know all the details when we write our code.
2. Accessing a Public Field
The easiest scenario is reading the value of a public String field. Public fields can be accessed without bypassing Java’s normal access rules, which makes the reflection process straightforward:
public class PublicFieldDemo {
public String name = "Baeldung";
}
@Test
void givenPublicStringField_whenAccessWithReflection_thenReturnValue() throws Exception {
PublicFieldDemo example = new PublicFieldDemo();
Field field = PublicFieldDemo.class.getField("name");
String value = (String) field.get(example);
assertEquals("Baeldung", value);
}
In this example, the getField(“name”) searches for a public field named “name” in the given class and its superclasses. If it’s found, we can call get(example) to retrieve its value from the instance.
Since the get method returns an Object, we cast it to a String before comparing it in our test.
3. Accessing a Private Field
In most applications, fields are private to follow the principles of encapsulation. Reflection can still access these fields, but we must explicitly override Java’s normal access checks:
public class PrivateFieldDemo {
private String secret = "Hidden Value";
}
@Test
void givenPrivateStringField_whenAccessWithReflection_thenReturnValue() throws Exception {
PrivateFieldDemo example = new PrivateFieldDemo();
Field field = PrivateFieldDemo.class.getDeclaredField("secret");
field.setAccessible(true);
String value = (String) field.get(example);
assertEquals("Hidden Value", value);
}
In this example, we use getDeclaredField(“secret”) instead of getField(). This method looks for the field in the class itself, regardless of whether it’s public, protected, or private, but it doesn’t search parent classes. Because the field is private, trying to access it without changing its accessibility would result in an IllegalAccessException.
By calling setAccessible(true), we temporarily disable Java’s access control checks for this field, allowing us to read its value. This technique is powerful but should be used cautiously, as it breaks encapsulation.
4. Reading a Field With a Dynamic Name
Sometimes, the field name isn’t known at compile time and is instead determined during program execution. This is common when working with dynamic data sources, such as reading field names from configuration files, mapping JSON keys to object fields, or adapting to database schema changes.
Reflection allows us to store the field name in a variable and still access the corresponding value:
public class DynamicFieldDemo {
public String title = "Dynamic Access";
}
@Test
void givenFieldNameVariable_whenAccessWithReflection_thenReturnValue() throws Exception {
DynamicFieldDemo example = new DynamicFieldDemo();
String fieldName = "title";
Field field = DynamicFieldDemo.class.getField(fieldName);
String value = (String) field.get(example);
assertEquals("Dynamic Access", value);
}
Here, the process is the same as when accessing a public field, except that instead of passing a hardcoded string, we pass a variable containing the field name. This approach is beneficial in generic utilities that must handle multiple objects and fields without hardcoding each name.
It allows the code to adapt at runtime, making it more flexible and reusable.
5. A Generic Utility Method
To avoid repeating reflection logic in multiple places, we can wrap it in a reusable method. This method will work for public and private fields, handle any type, and allow us to safely get a String value without worrying about null or type mismatches:
public class User {
private String username = "baeldung_user";
}
public static String getFieldValueAsString(Object obj, String fieldName) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
boolean accessible = field.canAccess(obj);
try {
if (!accessible) {
field.setAccessible(true);
}
return Objects.toString(field.get(obj), null);
} finally {
if (!accessible) {
field.setAccessible(false);
}
}
}
@Test
void givenObjectAndFieldName_whenUseUtilityMethod_thenReturnStringValue() throws Exception {
User user = new User();
String value = getFieldValueAsString(user, "username");
assertEquals("baeldung_user", value);
}
In this utility method, we use Objects.toString(field.get(obj), null) to safely convert the value to a String, returning null if the field is null.
6. Conclusion
In this article, we explored various methods for retrieving a String value from a Java field using reflection. Reflection offers flexibility, but it should be used carefully because it can bypass encapsulation and has a performance cost compared to direct field access.
As always, the source code is available over on GitHub.