ArrayUtils.toPrimitive(Boolean...) null array elements map to false,

like Boolean.parseBoolean(null) and its callers return false.

This also happens to address issues with catching NPEs reported by
Spotbugs 4.5.1 .
This commit is contained in:
Gary Gregory 2021-12-08 13:11:21 -05:00
parent d672dafa2e
commit 4369537d8b
5 changed files with 31 additions and 43 deletions

View File

@ -66,6 +66,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="CiprianBodnarescu">Use Set instead of List for checking the contains() method #734.</action> <action type="fix" dev="ggregory" due-to="CiprianBodnarescu">Use Set instead of List for checking the contains() method #734.</action>
<action type="fix" dev="kinow" due-to="Roland Kreuzer">Javadoc for StringUtils.substringBefore(String str, int separator) doesn't mention that the separator is an int.</action> <action type="fix" dev="kinow" due-to="Roland Kreuzer">Javadoc for StringUtils.substringBefore(String str, int separator) doesn't mention that the separator is an int.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in ThreadUtils.getSystemThreadGroup() when the current thread is stopped.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in ThreadUtils.getSystemThreadGroup() when the current thread is stopped.</action>
<action type="fix" dev="ggregory" due-to="Gary Gregory">ArrayUtils.toPrimitive(Boolean...) null array elements map to false, like Boolean.parseBoolean(null) and its callers return false.</action>
<!-- ADD --> <!-- ADD -->
<action type="add" dev="ggregory" due-to="Gary Gregory">Add EnumUtils.getEnumSystemProperty(...).</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add EnumUtils.getEnumSystemProperty(...).</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add TriConsumer.</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add TriConsumer.</action>

View File

@ -9250,23 +9250,15 @@ public class ArrayUtils {
* <p> * <p>
* This method returns {@code null} for a {@code null} input array. * This method returns {@code null} for a {@code null} input array.
* </p> * </p>
* <p>
* Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
* </p>
* *
* @param array a {@code Boolean} array, may be {@code null} * @param array a {@code Boolean} array, may be {@code null}
* @return a {@code boolean} array, {@code null} if null array input * @return a {@code boolean} array, {@code null} if null array input
* @throws NullPointerException if an array element is {@code null}
*/ */
public static boolean[] toPrimitive(final Boolean[] array) { public static boolean[] toPrimitive(final Boolean[] array) {
if (array == null) { return toPrimitive(array, false);
return null;
}
if (array.length == 0) {
return EMPTY_BOOLEAN_ARRAY;
}
final boolean[] result = new boolean[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = array[i].booleanValue();
}
return result;
} }
/** /**

View File

@ -101,7 +101,6 @@ public class BooleanUtils {
/** /**
* <p>Performs an 'and' operation on an array of Booleans.</p> * <p>Performs an 'and' operation on an array of Booleans.</p>
*
* <pre> * <pre>
* BooleanUtils.and(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
* BooleanUtils.and(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
@ -109,23 +108,22 @@ public class BooleanUtils {
* BooleanUtils.and(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
* BooleanUtils.and(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
* BooleanUtils.and(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE * BooleanUtils.and(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
* BooleanUtils.and(null, null) = Boolean.FALSE
* </pre> * </pre>
* <p>
* Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
* </p>
* *
* @param array an array of {@code Boolean}s * @param array an array of {@code Boolean}s
* @return the result of the logical 'and' operation. That is {@code false} * @return the result of the logical 'and' operation. That is {@code false}
* if any of the parameters is {@code false} and {@code true} otherwise. * if any of the parameters is {@code false} and {@code true} otherwise.
* @throws NullPointerException if {@code array} is {@code null} * @throws NullPointerException if {@code array} is {@code null}
* @throws IllegalArgumentException if {@code array} is empty. * @throws IllegalArgumentException if {@code array} is empty.
* @throws IllegalArgumentException if {@code array} contains a {@code null}
* @since 3.0.1 * @since 3.0.1
*/ */
public static Boolean and(final Boolean... array) { public static Boolean and(final Boolean... array) {
ObjectUtils.requireNonEmpty(array, "array"); ObjectUtils.requireNonEmpty(array, "array");
try { return and(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
return and(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
} catch (final NullPointerException ex) {
throw new IllegalArgumentException("The array must not contain any null elements");
}
} }
/** /**
@ -279,7 +277,6 @@ public class BooleanUtils {
/** /**
* <p>Performs an 'or' operation on an array of Booleans.</p> * <p>Performs an 'or' operation on an array of Booleans.</p>
*
* <pre> * <pre>
* BooleanUtils.or(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE * BooleanUtils.or(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
* BooleanUtils.or(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
@ -288,22 +285,22 @@ public class BooleanUtils {
* BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
* BooleanUtils.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE * BooleanUtils.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
* BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
* BooleanUtils.or(Boolean.TRUE, null) = Boolean.TRUE
* BooleanUtils.or(Boolean.FALSE, null) = Boolean.FALSE
* </pre> * </pre>
* <p>
* Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
* </p>
* *
* @param array an array of {@code Boolean}s * @param array an array of {@code Boolean}s
* @return {@code true} if any of the arguments is {@code true}, and it returns {@code false} otherwise. * @return {@code true} if any of the arguments is {@code true}, and it returns {@code false} otherwise.
* @throws NullPointerException if {@code array} is {@code null} * @throws NullPointerException if {@code array} is {@code null}
* @throws IllegalArgumentException if {@code array} is empty. * @throws IllegalArgumentException if {@code array} is empty.
* @throws IllegalArgumentException if {@code array} contains a {@code null}
* @since 3.0.1 * @since 3.0.1
*/ */
public static Boolean or(final Boolean... array) { public static Boolean or(final Boolean... array) {
ObjectUtils.requireNonEmpty(array, "array"); ObjectUtils.requireNonEmpty(array, "array");
try { return or(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
return or(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
} catch (final NullPointerException ex) {
throw new IllegalArgumentException("The array must not contain any null elements");
}
} }
/** /**
@ -1103,27 +1100,26 @@ public class BooleanUtils {
/** /**
* <p>Performs an xor on an array of Booleans.</p> * <p>Performs an xor on an array of Booleans.</p>
*
* <pre> * <pre>
* BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE }) = Boolean.FALSE * BooleanUtils.xor(Boolean.TRUE, Boolean.TRUE) = Boolean.FALSE
* BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE * BooleanUtils.xor(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
* BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }) = Boolean.TRUE * BooleanUtils.xor(Boolean.TRUE, Boolean.FALSE) = Boolean.TRUE
* BooleanUtils.xor(Boolean.TRUE, Boolean.FALSE, Boolean.FALSE) = Boolean.TRUE * BooleanUtils.xor(Boolean.TRUE, Boolean.FALSE, Boolean.FALSE) = Boolean.TRUE
* BooleanUtils.xor(Boolean.FALSE, null) = Boolean.FALSE
* BooleanUtils.xor(Boolean.TRUE, null) = Boolean.TRUE
* </pre> * </pre>
* <p>
* Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
* </p>
* *
* @param array an array of {@code Boolean}s * @param array an array of {@code Boolean}s
* @return the result of the xor operations * @return the result of the xor operations
* @throws NullPointerException if {@code array} is {@code null} * @throws NullPointerException if {@code array} is {@code null}
* @throws IllegalArgumentException if {@code array} is empty. * @throws IllegalArgumentException if {@code array} is empty.
* @throws IllegalArgumentException if {@code array} contains a {@code null}
*/ */
public static Boolean xor(final Boolean... array) { public static Boolean xor(final Boolean... array) {
ObjectUtils.requireNonEmpty(array, "array"); ObjectUtils.requireNonEmpty(array, "array");
try { return xor(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
return xor(ArrayUtils.toPrimitive(array)) ? Boolean.TRUE : Boolean.FALSE;
} catch (final NullPointerException ex) {
throw new IllegalArgumentException("The array must not contain any null elements");
}
} }
/** /**

View File

@ -6282,8 +6282,7 @@ public class ArrayUtilsTest {
assertNull(ArrayUtils.toPrimitive(b)); assertNull(ArrayUtils.toPrimitive(b));
assertSame(ArrayUtils.EMPTY_BOOLEAN_ARRAY, ArrayUtils.toPrimitive(new Boolean[0])); assertSame(ArrayUtils.EMPTY_BOOLEAN_ARRAY, ArrayUtils.toPrimitive(new Boolean[0]));
assertArrayEquals(new boolean[]{true, false, true}, ArrayUtils.toPrimitive(new Boolean[]{Boolean.TRUE, Boolean.FALSE, Boolean.TRUE})); assertArrayEquals(new boolean[]{true, false, true}, ArrayUtils.toPrimitive(new Boolean[]{Boolean.TRUE, Boolean.FALSE, Boolean.TRUE}));
assertArrayEquals(new boolean[]{true, false}, ArrayUtils.toPrimitive(new Boolean[]{Boolean.TRUE, null}));
assertThrows(NullPointerException.class, () -> ArrayUtils.toPrimitive(new Boolean[]{Boolean.TRUE, null}));
} }
@Test @Test

View File

@ -436,7 +436,7 @@ public class BooleanUtilsTest {
@Test @Test
public void testAnd_object_nullElementInput() { public void testAnd_object_nullElementInput() {
assertThrows(IllegalArgumentException.class, () -> BooleanUtils.and(new Boolean[] {null})); assertEquals(Boolean.FALSE, BooleanUtils.and(new Boolean[] {null}));
} }
@Test @Test
@ -635,7 +635,7 @@ public class BooleanUtilsTest {
@Test @Test
public void testOr_object_nullElementInput() { public void testOr_object_nullElementInput() {
assertThrows(IllegalArgumentException.class, () -> BooleanUtils.or(new Boolean[] {null})); assertEquals(Boolean.FALSE, BooleanUtils.or(new Boolean[] {null}));
} }
@Test @Test
@ -817,7 +817,7 @@ public class BooleanUtilsTest {
@Test @Test
public void testXor_object_nullElementInput() { public void testXor_object_nullElementInput() {
assertThrows(IllegalArgumentException.class, () -> BooleanUtils.xor(new Boolean[] {null})); assertEquals(Boolean.FALSE, BooleanUtils.xor(new Boolean[] {null}));
} }
@Test @Test