Add and use APIs to avoid compiler warnings and use of
@SuppressWarnings. - Add and use ArrayUtils.getComponentType(T[]). - Add and use ClassUtils.getComponentType(Class<T[]>). - Add and use ObjectUtils.getClass(T).
This commit is contained in:
parent
56e525d074
commit
27101b4739
|
@ -55,6 +55,9 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add TriConsumer.</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use EnumUtils.getFirstEnumIgnoreCase(Class, String, Function, E).</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use Suppliers.</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use ArrayUtils.getComponentType(T[]).</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use ClassUtils.getComponentType(Class<T[]>).</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use ObjectUtils.getClass(T).</action>
|
||||
<!-- UPDATE -->
|
||||
<action type="update" dev="ggregory" due-to="Dependabot, Gary Gregory">Bump spotbugs-maven-plugin from 4.2.0 to 4.2.3 #735.</action>
|
||||
<action type="update" dev="ggregory" due-to="Dependabot, XenoAmess">Bump Bump actions/cache from v2.1.4 to v2.1.5 #742, #752.</action>
|
||||
|
|
|
@ -743,17 +743,27 @@ public class ArrayUtils {
|
|||
*/
|
||||
@Deprecated
|
||||
public static <T> T[] add(final T[] array, final int index, final T element) {
|
||||
Class<?> clss = null;
|
||||
Class<T> clss = null;
|
||||
if (array != null) {
|
||||
clss = array.getClass().getComponentType();
|
||||
clss = getComponentType(array);
|
||||
} else if (element != null) {
|
||||
clss = element.getClass();
|
||||
clss = ObjectUtils.getClass(element);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Array and element cannot both be null");
|
||||
}
|
||||
@SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
|
||||
final T[] newArray = (T[]) add(array, index, element, clss);
|
||||
return newArray;
|
||||
return (T[]) add(array, index, element, clss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array's component type.
|
||||
*
|
||||
* @param <T> The array type.
|
||||
* @param array The array.
|
||||
* @return The component type.
|
||||
* @since 3.13.0
|
||||
*/
|
||||
public static <T> Class<T> getComponentType(final T[] array) {
|
||||
return ClassUtils.getComponentType(ObjectUtils.getClass(array));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3102,7 +3112,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
|
||||
}
|
||||
|
||||
final Class<?> type = array.getClass().getComponentType();
|
||||
final Class<T> type = getComponentType(array);
|
||||
@SuppressWarnings("unchecked") // OK, because array and values are of type T
|
||||
final
|
||||
T[] result = (T[]) Array.newInstance(type, array.length + values.length);
|
||||
|
@ -3786,10 +3796,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
|
||||
if (isEmpty(array)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if (isEmpty(array) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -3832,10 +3839,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -3880,10 +3884,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 2.1
|
||||
*/
|
||||
public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -3943,10 +3944,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
|
||||
if (isEmpty(array)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if (isEmpty(array) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -3978,10 +3976,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
|
||||
if (isEmpty(array)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if (isEmpty(array) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -4027,10 +4022,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
|
||||
if (isEmpty(array)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if (isEmpty(array) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -4073,10 +4065,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -4119,10 +4108,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -4165,10 +4151,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -4219,10 +4202,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
|
||||
*/
|
||||
public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
|
||||
if (array == null) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex < 0) {
|
||||
if ((array == null) || (startIndex < 0)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
if (startIndex >= array.length) {
|
||||
|
@ -6982,10 +6962,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7061,10 +7038,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7140,10 +7114,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7219,10 +7190,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7298,10 +7266,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7377,10 +7342,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7456,10 +7418,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7537,10 +7496,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -7616,10 +7572,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
* @since 3.5
|
||||
*/
|
||||
public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
if ((array == null) || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
|
||||
return;
|
||||
}
|
||||
if (startIndexInclusive < 0) {
|
||||
|
@ -8243,7 +8196,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd
|
|||
endIndexExclusive = array.length;
|
||||
}
|
||||
final int newSize = endIndexExclusive - startIndexInclusive;
|
||||
final Class<?> type = array.getClass().getComponentType();
|
||||
final Class<T> type = getComponentType(array);
|
||||
if (newSize <= 0) {
|
||||
@SuppressWarnings("unchecked") // OK, because array is of type T
|
||||
final T[] emptyArray = (T[]) Array.newInstance(type, 0);
|
||||
|
|
|
@ -1120,6 +1120,20 @@ public class ClassUtils {
|
|||
return getClass(loader, className, initialize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Class#getComponentType()} using generics.
|
||||
*
|
||||
* @param <T> The array class type.
|
||||
* @param cls A class or null.
|
||||
* @return The array component type or null.
|
||||
* @see Class#getComponentType()
|
||||
* @since 3.13.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> getComponentType(final Class<T[]> cls) {
|
||||
return cls == null ? null : (Class<T>) cls.getComponentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the desired Method much like {@code Class.getMethod}, however
|
||||
* it ensures that the returned Method is from a public class or interface and not
|
||||
|
|
|
@ -673,6 +673,19 @@ public class ObjectUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Object#getClass()} using generics.
|
||||
*
|
||||
* @param <T> The argument type or null.
|
||||
* @param object The argument.
|
||||
* @return The argument Class or null.
|
||||
* @since 3.13.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> getClass(final T object) {
|
||||
return object == null ? null : (Class<T>) object.getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Executes the given suppliers in order and returns the first return
|
||||
* value where a value other than {@code null} is returned.
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
|
@ -266,14 +267,11 @@ public class EventListenerSupport<L> implements Serializable {
|
|||
*/
|
||||
private void readObject(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
@SuppressWarnings("unchecked") // Will throw CCE here if not correct
|
||||
final
|
||||
L[] srcListeners = (L[]) objectInputStream.readObject();
|
||||
final L[] srcListeners = (L[]) objectInputStream.readObject();
|
||||
|
||||
this.listeners = new CopyOnWriteArrayList<>(srcListeners);
|
||||
|
||||
@SuppressWarnings("unchecked") // Will throw CCE here if not correct
|
||||
final
|
||||
Class<L> listenerInterface = (Class<L>) srcListeners.getClass().getComponentType();
|
||||
final Class<L> listenerInterface = ArrayUtils.getComponentType(srcListeners);
|
||||
|
||||
initializeTransientFields(listenerInterface, Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
@ -285,8 +283,7 @@ public class EventListenerSupport<L> implements Serializable {
|
|||
*/
|
||||
private void initializeTransientFields(final Class<L> listenerInterface, final ClassLoader classLoader) {
|
||||
@SuppressWarnings("unchecked") // Will throw CCE here if not correct
|
||||
final
|
||||
L[] array = (L[]) Array.newInstance(listenerInterface, 0);
|
||||
final L[] array = (L[]) Array.newInstance(listenerInterface, 0);
|
||||
this.prototypeArray = array;
|
||||
createProxy(listenerInterface, classLoader);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.junit.jupiter.api.Test;
|
|||
public class ArrayUtilsTest {
|
||||
|
||||
private class TestClass {
|
||||
// empty
|
||||
}
|
||||
|
||||
/** A predefined seed used to initialize {@link Random} in order to get predictable results */
|
||||
|
@ -213,13 +214,16 @@ public class ArrayUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testContains_LANG_1261() {
|
||||
|
||||
class LANG1261ParentObject {
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class LANG1261ChildObject extends LANG1261ParentObject {
|
||||
// empty.
|
||||
}
|
||||
|
||||
final Object[] array = new LANG1261ChildObject[]{new LANG1261ChildObject()};
|
||||
|
@ -403,6 +407,15 @@ public class ArrayUtilsTest {
|
|||
assertEquals(null, ArrayUtils.get(array1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentType() {
|
||||
final TestClass[] newArray = {};
|
||||
// No type-cast required.
|
||||
final Class<TestClass> componentType = ArrayUtils.getComponentType(newArray);
|
||||
assertEquals(TestClass.class, componentType);
|
||||
assertNull(ArrayUtils.getComponentType(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefault() {
|
||||
// null default
|
||||
|
@ -656,7 +669,6 @@ public class ArrayUtilsTest {
|
|||
assertEquals(emptySet, ArrayUtils.indexesOf(array, 'e', 0));
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Test
|
||||
public void testIndexesOfDouble() {
|
||||
double[] array = null;
|
||||
|
@ -700,7 +712,6 @@ public class ArrayUtilsTest {
|
|||
assertEquals(testSet, ArrayUtils.indexesOf(array, 1.00001324, 0.0001));
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Test
|
||||
public void testIndexesOfDoubleWithStartIndex() {
|
||||
double[] array = null;
|
||||
|
@ -753,7 +764,6 @@ public class ArrayUtilsTest {
|
|||
assertEquals(testSet, ArrayUtils.indexesOf(array, 1.00001324, 0, 0.0001));
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Test
|
||||
public void testIndexesOfFloat() {
|
||||
float[] array = null;
|
||||
|
@ -776,7 +786,6 @@ public class ArrayUtilsTest {
|
|||
assertEquals(emptySet, ArrayUtils.indexesOf(array, 99));
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
@Test
|
||||
public void testIndexesOfFloatWithStartIndex() {
|
||||
float[] array = null;
|
||||
|
|
|
@ -1234,6 +1234,17 @@ public class ClassUtilsTest {
|
|||
assertGetClassReturnsClass( boolean[][].class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentType() {
|
||||
final CX[] newArray = {};
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<CX[]> classCxArray = (Class<CX[]>) newArray.getClass();
|
||||
// No type-cast required.
|
||||
final Class<CX> componentType = ClassUtils.getComponentType(classCxArray);
|
||||
assertEquals(CX.class, componentType);
|
||||
assertNull(ClassUtils.getComponentType(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInnerClass() throws ClassNotFoundException {
|
||||
assertEquals( Inner.DeeplyNested.class, ClassUtils.getClass( "org.apache.commons.lang3.ClassUtilsTest.Inner.DeeplyNested" ) );
|
||||
|
|
|
@ -421,6 +421,15 @@ public class ObjectUtilsTest {
|
|||
assertNull(ObjectUtils.firstNonNull((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClass() {
|
||||
final String[] newArray = ArrayUtils.EMPTY_STRING_ARRAY;
|
||||
// No type-cast required.
|
||||
final Class<String[]> cls = ObjectUtils.getClass(newArray);
|
||||
assertEquals(String[].class, cls);
|
||||
assertNull(ObjectUtils.getClass(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFirstNonNull() {
|
||||
// first non null
|
||||
|
|
Loading…
Reference in New Issue