Add initialize(..) operator to promote initialization safety.

The initialize operator replaces the common initialization safety pattern using an if-then-else or Java's ternary operator to ensure that a collaborator reference has bee properly initialized:

target = target != null ? target : new Target();
This commit is contained in:
John Blum
2020-07-08 13:26:57 -07:00
parent 2da58cc548
commit 251f762c2d
2 changed files with 61 additions and 2 deletions

View File

@@ -27,6 +27,7 @@ import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.geode.pdx.PdxInstance;
@@ -258,6 +259,33 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils {
return doOperationSafely(() -> (T) field.get(obj), (T) null);
}
/**
* An initialization operator used to evalutate a given {@link Object target} and conditionally
* {@link Supplier supply} a new value if the {@link Object target} is {@literal null}.
*
* The {@code initialize} operator simplifies a common initialization safety pattern that appears in code as:
*
* <code>
* target = target != null ? target : new Target();
* </code>
*
* While the expression uses Java's ternary operator, users could very well use a if-then-else statement instead.
* Either way, since Java is {@literal call-by-value} then the above statement and expression can be replaced with:
*
* <code>
* target = initialize(target, Target::new);
* </code>
*
* @param <T> {@link Class type} of the {@link Object target}.
* @param target {@link Object} to evaluate and initialize; must not be {@literal null}.
* @param supplier {@link Supplier} used to initialize the {@link Object target} on return.
* @return the existing {@link Object target} if not {@literal null}, otherwise invoke the {@link Supplier}
* to supply a new instance of {@link T}.
*/
public static <T> T initialize(@Nullable T target, @NonNull Supplier<T> supplier) {
return target != null ? target : supplier.get();
}
/**
* Invokes a {@link Method} on an {@link Object} with the given {@link String name}.
*
@@ -281,13 +309,27 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils {
methodName, org.springframework.util.ObjectUtils.nullSafeClassName(obj)));
}
public static Constructor makeAccessible(Constructor<?> constructor) {
/**
* Makes the {@link Constructor} accessible.
*
* @param constructor {@link Constructor} to make accessible; must not be {@literal null}.
* @return the given {@link Constructor}.
* @see java.lang.reflect.Constructor
*/
public static Constructor makeAccessible(@NonNull Constructor<?> constructor) {
ReflectionUtils.makeAccessible(constructor);
return constructor;
}
/**
* Makes the {@link Field} accessible.
*
* @param field {@link Field} to make accessible; must not be {@literal null}.
* @return the given {@link Field}.
* @see java.lang.reflect.Field
*/
public static Field makeAccessible(Field field) {
ReflectionUtils.makeAccessible(field);
@@ -295,6 +337,13 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils {
return field;
}
/**
* Makes the {@link Method} accessible.
*
* @param constructor {@link Method} to make accessible; must not be {@literal null}.
* @return the given {@link Method}.
* @see java.lang.reflect.Method
*/
public static Method makeAccessible(Method method) {
ReflectionUtils.makeAccessible(method);

View File

@@ -95,7 +95,7 @@ public class ObjectUtilsUnitTests {
}
@Test(expected = IllegalArgumentException.class)
public void asPdxInstanceTypeReturnNonMatchingType() {
public void asPdxInstanceTypeReturningNonMatchingType() {
C source = new C();
@@ -300,6 +300,16 @@ public class ObjectUtilsUnitTests {
}
}
@Test
public void initializeWithNonNullTarget() {
assertThat(ObjectUtils.initialize("test", () -> "mock")).isEqualTo("test");
}
@Test
public void initializeWithNullTarget() {
assertThat(ObjectUtils.initialize(null, () -> "mock")).isEqualTo("mock");
}
@Test
public void invokeMethodOnObjectReturnsValue() {
assertThat(ObjectUtils.<String>invoke(new TestObject(), "testMethod")).isEqualTo("TEST");