Skip to content

Commit

Permalink
Introduce overloaded readFieldValue() variants in ReflectionUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrannen committed Jan 20, 2018
1 parent 179fd55 commit 479931c
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 8 deletions.
Expand Up @@ -360,7 +360,7 @@ public static <T> T newInstance(Constructor<T> constructor, Object... args) {
}

/**
* Read the value of a potentially inaccessible field.
* Read the value of a potentially inaccessible or nonexistent field.
*
* <p>If the field does not exist, an exception occurs while reading it, or
* the value of the field is {@code null}, an empty {@link Optional} is
Expand All @@ -370,13 +370,55 @@ public static <T> T newInstance(Constructor<T> constructor, Object... args) {
* @param fieldName the name of the field; never {@code null} or empty
* @param instance the instance from where the value is to be read; may
* be {@code null} for a static field
* @see #readFieldValue(Field)
* @see #readFieldValue(Field, Object)
*/
public static <T> Optional<Object> readFieldValue(Class<T> clazz, String fieldName, T instance) {
Preconditions.notNull(clazz, "Class must not be null");
Preconditions.notBlank(fieldName, "Field name must not be null or blank");

Field field = null;
try {
field = makeAccessible(clazz.getDeclaredField(fieldName));
}
catch (Throwable t) {
BlacklistedExceptions.rethrowIfBlacklisted(t);
return Optional.empty();
}
return readFieldValue(field, instance);
}

/**
* Read the value of a potentially inaccessible static field.
*
* <p>If an exception occurs while reading the field or if the value of the
* field is {@code null}, an empty {@link Optional} is returned.
*
* @param field the field to read; never {@code null}
* @see #readFieldValue(Field, Object)
* @see #readFieldValue(Class, String, Object)
*/
public static Optional<Object> readFieldValue(Field field) {
return readFieldValue(field, null);
}

/**
* Read the value of a potentially inaccessible field.
*
* <p>If an exception occurs while reading the field or if the value of the
* field is {@code null}, an empty {@link Optional} is returned.
*
* @param field the field to read; never {@code null}
* @param instance the instance from which the value is to be read; may
* be {@code null} for a static field
* @see #readFieldValue(Field)
* @see #readFieldValue(Class, String, Object)
*/
public static <T> Optional<Object> readFieldValue(Field field, T instance) {
Preconditions.notNull(field, "Field must not be null");

try {
Field field = makeAccessible(clazz.getDeclaredField(fieldName));
makeAccessible(field);
return Optional.ofNullable(field.get(instance));
}
catch (Throwable t) {
Expand Down
Expand Up @@ -34,6 +34,7 @@
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
Expand Down Expand Up @@ -162,13 +163,34 @@ void newInstance() {
}

@Test
void readFieldValueOfExistingField() {
assertThat(readFieldValue(MyClass.class, "value", new MyClass(42))).contains(42);
void readFieldValueOfNonexistentStaticField() {
assertThat(readFieldValue(MyClass.class, "doesNotExist", null)).isNotPresent();
assertThat(readFieldValue(MySubClass.class, "staticField", null)).isNotPresent();
}

@Test
void readFieldValueOfMissingField() {
assertThat(readFieldValue(MyClass.class, "doesNotExist", new MyClass(42))).isEmpty();
void readFieldValueOfNonexistentInstanceField() {
assertThat(readFieldValue(MyClass.class, "doesNotExist", new MyClass(42))).isNotPresent();
assertThat(readFieldValue(MyClass.class, "doesNotExist", new MySubClass(42))).isNotPresent();
}

@Test
void readFieldValueOfExistingStaticField() throws Exception {
assertThat(readFieldValue(MyClass.class, "staticField", null)).contains(42);

Field field = MyClass.class.getDeclaredField("staticField");
assertThat(readFieldValue(field)).contains(42);
assertThat(readFieldValue(field, null)).contains(42);
}

@Test
void readFieldValueOfExistingInstanceField() throws Exception {
MyClass instance = new MyClass(42);
assertThat(readFieldValue(MyClass.class, "instanceField", instance)).contains(42);

Field field = MyClass.class.getDeclaredField("instanceField");
assertThat(readFieldValue(field, instance)).contains(42);
assertThat(readFieldValue(field, null)).isNotPresent();
}

@Test
Expand Down Expand Up @@ -1136,10 +1158,19 @@ static class Exploder {

static class MyClass {

final int value;
static final int staticField = 42;

final int instanceField;

MyClass(int value) {
this.value = value;
this.instanceField = value;
}
}

static class MySubClass extends MyClass {

MySubClass(int value) {
super(value);
}
}

Expand Down

0 comments on commit 479931c

Please sign in to comment.