Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecated ObjectUtils defaultIfNull in favor or getIfNull overload getFirstNonNull with collection support #1355

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions src/main/java/org/apache/commons/lang3/ObjectUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ public static short CONST_SHORT(final int v) {
* @param object the {@link Object} to test, may be {@code null}
* @param defaultValue the default value to return, may be {@code null}
* @return {@code object} if it is not {@code null}, defaultValue otherwise
* TODO Rename to getIfNull in 4.0
* @deprecated use {@link ObjectUtils#getIfNull(Object, Object)}
*/
public static <T> T defaultIfNull(final T object, final T defaultValue) {
return object != null ? object : defaultValue;
Expand Down Expand Up @@ -640,6 +640,35 @@ public static <T> T firstNonNull(final T... values) {
return Streams.of(values).filter(Objects::nonNull).findFirst().orElse(null);
}

/**
* Returns the first non-null value in the collection. If all values are {@code null},
* or if the collection is {@code null} or empty, {@code null} is returned.
*
* <p>Examples:
* <pre>
* ObjectUtils.firstNonNull(Arrays.asList(null, null)) = null
* ObjectUtils.firstNonNull(Arrays.asList(null, "")) = ""
* ObjectUtils.firstNonNull(Arrays.asList(null, null, "")) = ""
* ObjectUtils.firstNonNull(Arrays.asList(null, "zz")) = "zz"
* ObjectUtils.firstNonNull(Arrays.asList("abc", *)) = "abc"
* ObjectUtils.firstNonNull(Arrays.asList(null, "xyz", *)) = "xyz"
* ObjectUtils.firstNonNull(Arrays.asList(Boolean.TRUE, *)) = Boolean.TRUE
* ObjectUtils.firstNonNull(Collections.emptyList()) = null
* ObjectUtils.firstNonNull(null) = null
* </pre>
*
* @param <T> the type of elements in the collection
* @param values the collection to test, may be {@code null} or empty
* @return the first non-null value in the collection, or {@code null} if no non-null value is found
* @since 3.18.0
*/
public static <T> T firstNonNull(final Collection<T> values) {
if (Objects.isNull(values) || values.isEmpty()) {
return null;
}
return values.stream().filter(Objects::nonNull).findFirst().orElse(null);
}

/**
* Delegates to {@link Object#getClass()} using generics.
*
Expand Down Expand Up @@ -706,7 +735,27 @@ public static <T> T getFirstNonNull(final Supplier<T>... suppliers) {
* @since 3.10
*/
public static <T> T getIfNull(final T object, final Supplier<T> defaultSupplier) {
return object != null ? object : Suppliers.get(defaultSupplier);
return Objects.nonNull(object) ? object : Suppliers.get(defaultSupplier);
}

/**
* Returns a default value if the object passed is {@code null}.
*
* <pre>
* ObjectUtils.getIfNull(null, null) = null
* ObjectUtils.getIfNull(null, "") = ""
* ObjectUtils.getIfNull(null, "zz") = "zz"
* ObjectUtils.getIfNull("abc", *) = "abc"
* ObjectUtils.getIfNull(Boolean.TRUE, *) = Boolean.TRUE
* </pre>
*
* @param <T> the type of the object
* @param object the {@link Object} to test, may be {@code null}
* @param defaultValue the default value to return, may be {@code null}
* @return {@code object} if it is not {@code null}, defaultValue otherwise
*/
public static <T> T getIfNull(final T object, final T defaultValue) {
return Objects.nonNull(object) ? object : defaultValue;
}

/**
Expand Down Expand Up @@ -965,7 +1014,7 @@ their constant using one of the CONST() utility methods, instead:
* @since 3.13.0
*/
public static boolean isArray(final Object object) {
return object != null && object.getClass().isArray();
return Objects.nonNull(object) && object.getClass().isArray();
}

/**
Expand Down Expand Up @@ -1382,7 +1431,7 @@ public static void wait(final Object obj, final Duration duration) throws Interr
/**
* {@link ObjectUtils} instances should NOT be constructed in
* standard programming. Instead, the static methods on the class should
* be used, such as {@code ObjectUtils.defaultIfNull("a","b");}.
* be used, such as {@code ObjectUtils.getIfNull("a","b");}.
*
* <p>This constructor is public to permit tools that require a JavaBean
* instance to operate.</p>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/apache/commons/lang3/builder/Diff.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public abstract class Diff<T> extends Pair<T, T> {
*/
protected Diff(final String fieldName) {
this.fieldName = Objects.requireNonNull(fieldName);
this.type = ObjectUtils.defaultIfNull(TypeUtils.getTypeArguments(getClass(), Diff.class).get(Diff.class.getTypeParameters()[0]), Object.class);
this.type = ObjectUtils.getIfNull(TypeUtils.getTypeArguments(getClass(), Diff.class).get(Diff.class.getTypeParameters()[0]), Object.class);
}

Diff(final String fieldName, final Type type) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ private static final class WildcardTypeImpl implements WildcardType {
* @param lowerBounds of this type
*/
private WildcardTypeImpl(final Type[] upperBounds, final Type[] lowerBounds) {
this.upperBounds = ObjectUtils.defaultIfNull(upperBounds, ArrayUtils.EMPTY_TYPE_ARRAY);
this.lowerBounds = ObjectUtils.defaultIfNull(lowerBounds, ArrayUtils.EMPTY_TYPE_ARRAY);
this.upperBounds = ObjectUtils.getIfNull(upperBounds, ArrayUtils.EMPTY_TYPE_ARRAY);
this.lowerBounds = ObjectUtils.getIfNull(lowerBounds, ArrayUtils.EMPTY_TYPE_ARRAY);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public static Formatter append(final CharSequence seq, final Formatter formatter
"Specified ellipsis '%1$s' exceeds precision of %2$s", ellipsis, Integer.valueOf(precision));
final StringBuilder buf = new StringBuilder(seq);
if (precision >= 0 && precision < seq.length()) {
final CharSequence actualEllipsis = ObjectUtils.defaultIfNull(ellipsis, StringUtils.EMPTY);
final CharSequence actualEllipsis = ObjectUtils.getIfNull(ellipsis, StringUtils.EMPTY);
buf.replace(precision - actualEllipsis.length(), seq.length(), actualEllipsis.toString());
}
final boolean leftJustify = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public static int toMillisInt(final Duration duration) {
* @return The given duration or {@link Duration#ZERO}.
*/
public static Duration zeroIfNull(final Duration duration) {
return ObjectUtils.defaultIfNull(duration, Duration.ZERO);
return ObjectUtils.getIfNull(duration, Duration.ZERO);
}

/**
Expand Down
41 changes: 40 additions & 1 deletion src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,9 @@ public void testConstructor() {
assertFalse(Modifier.isFinal(ObjectUtils.class.getModifiers()));
}

/**
* @deprecated
*/
@Test
public void testDefaultIfNull() {
final Object o = FOO;
Expand All @@ -444,6 +447,27 @@ public void testDefaultIfNull() {
assertEquals(1, callsCounter.getValue());
}

@Test
public void testGetIfNull() {
final Object o = FOO;
final Object dflt = BAR;
assertSame(dflt, ObjectUtils.getIfNull(null, dflt), "dflt was not returned when o was null");
assertSame(o, ObjectUtils.getIfNull(o, dflt), "dflt was returned when o was not null");
assertSame(dflt, ObjectUtils.getIfNull(null, () -> dflt), "dflt was not returned when o was null");
assertSame(o, ObjectUtils.getIfNull(o, () -> dflt), "dflt was returned when o was not null");
assertSame(o, ObjectUtils.getIfNull(FOO, () -> dflt), "dflt was returned when o was not null");
assertSame(o, ObjectUtils.getIfNull("foo", () -> dflt), "dflt was returned when o was not null");
final MutableInt callsCounter = new MutableInt(0);
final Supplier<Object> countingDefaultSupplier = () -> {
callsCounter.increment();
return dflt;
};
ObjectUtils.getIfNull(o, countingDefaultSupplier);
assertEquals(0, callsCounter.getValue());
ObjectUtils.getIfNull(null, countingDefaultSupplier);
assertEquals(1, callsCounter.getValue());
}

@Test
public void testEquals() {
assertTrue(ObjectUtils.equals(null, null), "ObjectUtils.equals(null, null) returned false");
Expand All @@ -454,7 +478,7 @@ public void testEquals() {
}

@Test
public void testFirstNonNull() {
public void testFirstNonNullArray() {
assertEquals("", ObjectUtils.firstNonNull(null, ""));
final String firstNonNullGenerics = ObjectUtils.firstNonNull(null, null, "123", "456");
assertEquals("123", firstNonNullGenerics);
Expand All @@ -471,6 +495,21 @@ public void testFirstNonNull() {
assertNull(ObjectUtils.firstNonNull((Object[]) null));
}

@Test
void testFirstNonNullCollection() {
// Test with a collection containing nulls and non-null values
assertEquals("123", ObjectUtils.firstNonNull(Arrays.asList(null, null, "123", "456")));
assertEquals("", ObjectUtils.firstNonNull(Collections.singletonList("")));
assertEquals("123", ObjectUtils.firstNonNull(Arrays.asList("123", null, "456", null)));
assertSame(Boolean.TRUE, ObjectUtils.firstNonNull(Collections.singletonList(Boolean.TRUE)));

// Test with an empty collection (should return null)
assertNull(ObjectUtils.firstNonNull(Collections.emptyList()));

// Test with a collection containing only nulls (should return null)
assertNull(ObjectUtils.firstNonNull(Arrays.asList(null, null)));
}

@Test
public void testGetClass() {
final String[] newArray = ArrayUtils.EMPTY_STRING_ARRAY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
*
* This class is somewhat redundant with regards to {@link ObjectUtils}.
* For example, {@link #requireNonNull(Object, Object)} is almost equivalent
* with {@link ObjectUtils#defaultIfNull(Object, Object)}. However, it isn't
* with {@link ObjectUtils#getIfNull(Object, Object)}. However, it isn't
* quite the same, because the latter can, in fact, return null. The former
* can't, and the Java compiler confirms this.(An alternative to redundancy
* would have been to change the {@code ObjectUtils} class. However, that
Expand Down