All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.iherus.shiro.util.Utils Maven / Gradle / Ivy

/**
 * Copyright (c) 2016-2019, Bosco.Liao ([email protected]).
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.iherus.shiro.util;

import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.UndeclaredThrowableException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
 * 工具类
 * 
 * @author Bosco.Liao
 * @since 2.0.0
 */
public abstract class Utils {

	private static final int INITIAL_HASH = 7;
	private static final int MULTIPLIER = 31;
	private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
	private static final String[] EMPTY_STRING_ARRAY = {};
	private static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
	private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
	private static final Map, SoftReference> LOCAL_FIELDS = new ConcurrentHashMap<>(128);
	private static final Map, SoftReference> LOCAL_METHODS = new ConcurrentHashMap<>(128);
	private static final Charset UTF_8 = Charset.forName("UTF-8");
	
	@SuppressWarnings("unchecked")
	public static  MutableArray newMutableArray(T... elements) {
		return new MutableArray(elements);
	}
	
	/************************ Assert about***********************/
	
	/**
	 * Assert that the given String contains valid text content; that is, it must not
	 * be {@code null} and must contain at least one non-whitespace character.
	 * 
Utils.assertNotBlank(name, "'name' must not be empty");
*/ public static void assertNotBlank(String text, String message) { if (!isNotBlank(text)) { throw new IllegalArgumentException(message); } } /** * Assert whether the object is {@code null}. */ public static void assertNotNull(Object object, String message) { if (object == null) { throw new IllegalArgumentException(message); } } /** * Assert a boolean expression, throwing an {@code IllegalArgumentException} * if the expression evaluates to {@code false}. *
	 * Utils.assertIsTrue(i > 0, () -> "The value '" + i + "' must be greater than zero");
	 * 
*/ public static void assertIsTrue(boolean expression, Supplier messageSupplier) { if (!expression) { throw new IllegalArgumentException(nullSafeGet(messageSupplier)); } } private static String nullSafeGet(Supplier messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } /** * Whether the CharSequence is empty. */ public static boolean isEmpty(final CharSequence cs) { return cs == null || cs.length() == 0; } /** * Whether the CharSequence is not empty. */ public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); } /** * Whether the CharSequence is blank. */ public static boolean isBlank(final CharSequence cs) { int strLen; if (cs == null || (strLen = cs.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(cs.charAt(i)) == false) { return false; } } return true; } /** * Whether the CharSequence is not blank. */ public static boolean isNotBlank(final CharSequence cs) { return !isBlank(cs); } /** * Split a {@code String} at the first occurrence of the delimiter. * Does not include the delimiter in the result. * @param toSplit the string to split (potentially {@code null} or empty) * @param delimiter to split the string up with (potentially {@code null} or empty) * @return a two element array with index 0 being before the delimiter, and * index 1 being after the delimiter (neither element includes the delimiter); * or {@code null} if the delimiter wasn't found in the given input {@code String} */ public static String[] split(String toSplit, String delimiter) { if (!hasLength(toSplit) || !hasLength(delimiter)) { return null; } int offset = toSplit.indexOf(delimiter); if (offset < 0) { return null; } String beforeDelimiter = toSplit.substring(0, offset); String afterDelimiter = toSplit.substring(offset + delimiter.length()); return new String[] { beforeDelimiter, afterDelimiter }; } /** * Convert a comma delimited list (e.g., a row from a CSV file) into a set. *

Note that this will suppress duplicates, and as of 4.2, the elements in * the returned set will preserve the original order in a {@link LinkedHashSet}. * @param str the input {@code String} (potentially {@code null} or empty) * @return a set of {@code String} entries in the list */ public static Set commaDelimitedListToSet(String str) { String[] tokens = commaDelimitedListToStringArray(str); return new LinkedHashSet<>(Arrays.asList(tokens)); } /** * Convert a comma delimited list (e.g., a row from a CSV file) into an * array of strings. * @param str the input {@code String} (potentially {@code null} or empty) * @return an array of strings, or the empty array in case of empty input */ public static String[] commaDelimitedListToStringArray(String str) { return delimitedListToStringArray(str, ","); } /** * Take a {@code String} that is a delimited list and convert it into a * {@code String} array. */ public static String[] delimitedListToStringArray(String str, String delimiter) { return delimitedListToStringArray(str, delimiter, null); } /** * Take a {@code String} that is a delimited list and convert it into * a {@code String} array. */ public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { if (str == null) { return EMPTY_STRING_ARRAY; } if (delimiter == null) { return new String[] { str }; } List result = new ArrayList<>(); if (delimiter.isEmpty()) { for (int i = 0; i < str.length(); i++) { result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); } } else { int pos = 0; int delPos; while ((delPos = str.indexOf(delimiter, pos)) != -1) { result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); pos = delPos + delimiter.length(); } if (str.length() > 0 && pos <= str.length()) { // Add rest of String, but not in case of empty input. result.add(deleteAny(str.substring(pos), charsToDelete)); } } return toStringArray(result); } /** * Copy the given {@link Collection} into a {@code String} array. *

The {@code Collection} must contain {@code String} elements only. * @param collection the {@code Collection} to copy * (potentially {@code null} or empty) * @return the resulting {@code String} array */ public static String[] toStringArray(Collection collection) { return (!isEmpty(collection) ? collection.toArray(EMPTY_STRING_ARRAY) : EMPTY_STRING_ARRAY); } /** * Return {@code true} if the supplied Collection is {@code null} or empty. * Otherwise, return {@code false}. * @param collection the Collection to check * @return whether the given Collection is empty */ public static boolean isEmpty(Collection collection) { return (collection == null || collection.isEmpty()); } /** * Delete any character in a given {@code String}. * @param inString the original {@code String} * @param charsToDelete a set of characters to delete. * E.g. "az\n" will delete 'a's, 'z's and new lines. * @return the resulting {@code String} */ public static String deleteAny(String inString, String charsToDelete) { if (!hasLength(inString) || !hasLength(charsToDelete)) { return inString; } StringBuilder sb = new StringBuilder(inString.length()); for (int i = 0; i < inString.length(); i++) { char c = inString.charAt(i); if (charsToDelete.indexOf(c) == -1) { sb.append(c); } } return sb.toString(); } /** * Check that the given {@code String} is neither {@code null} nor of length 0. *

Note: this method returns {@code true} for a {@code String} that * purely consists of whitespace. * @param str the {@code String} to check (may be {@code null}) * @return {@code true} if the {@code String} is not {@code null} and has length */ public static boolean hasLength(String str) { return (str != null && !str.isEmpty()); } /************************ Byte[] about ***********************/ public static String bytesToText(byte[] bytes) { return new String(bytes, UTF_8); } /** * numeric {@code long} to byte array. */ public static byte[] intToBytes(int number) { return String.valueOf(number).getBytes(UTF_8); } public static byte[] longToBytes(long number) { return String.valueOf(number).getBytes(UTF_8); } /** * Clones an array returning a typecast result and handling {@code null}. */ public static byte[] clone(final byte[] array) { if (array == null) { return null; } return array.clone(); } /** * Whether the byte array is empty. */ public static boolean isEmpty(final byte[] array) { return (array == null || array.length == 0); } /** * Whether the byte[] array is empty. */ public static boolean isEmpty(final byte[][] array) { return (array == null || array.length == 0); } /** * Merges all the elements of the given arrays into a new array. */ public static byte[] mergeAll(final byte[] array1, final byte... array2) { if (array1 == null) { return clone(array2); } else if (array2 == null) { return clone(array1); } final byte[] joinedArray = new byte[array1.length + array2.length]; System.arraycopy(array1, 0, joinedArray, 0, array1.length); System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); return joinedArray; } /** * Produces a new {@code byte} array containing the elements between the start * and end indices. */ public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) { if (array == null) { return null; } if (startIndexInclusive < 0) { startIndexInclusive = 0; } if (endIndexExclusive > array.length) { endIndexExclusive = array.length; } final int newSize = endIndexExclusive - startIndexInclusive; if (newSize <= 0) { return EMPTY_BYTE_ARRAY; } final byte[] subarray = new byte[newSize]; System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); return subarray; } /************************ Hashcode about***********************/ /** * Return as hash code for the given object; typically the value of * {@code Object#hashCode()}}. If the object is an array, * this method will delegate to any of the {@code nullSafeHashCode} * methods for arrays in this class. If the object is {@code null}, * this method returns 0. * @see Object#hashCode() * @see #nullSafeHashCode(Object[]) * @see #nullSafeHashCode(boolean[]) * @see #nullSafeHashCode(byte[]) * @see #nullSafeHashCode(char[]) * @see #nullSafeHashCode(double[]) * @see #nullSafeHashCode(float[]) * @see #nullSafeHashCode(int[]) * @see #nullSafeHashCode(long[]) * @see #nullSafeHashCode(short[]) */ public static int nullSafeHashCode(Object obj) { if (obj == null) { return 0; } if (obj.getClass().isArray()) { if (obj instanceof Object[]) { return nullSafeHashCode((Object[]) obj); } if (obj instanceof boolean[]) { return nullSafeHashCode((boolean[]) obj); } if (obj instanceof byte[]) { return nullSafeHashCode((byte[]) obj); } if (obj instanceof char[]) { return nullSafeHashCode((char[]) obj); } if (obj instanceof double[]) { return nullSafeHashCode((double[]) obj); } if (obj instanceof float[]) { return nullSafeHashCode((float[]) obj); } if (obj instanceof int[]) { return nullSafeHashCode((int[]) obj); } if (obj instanceof long[]) { return nullSafeHashCode((long[]) obj); } if (obj instanceof short[]) { return nullSafeHashCode((short[]) obj); } } return obj.hashCode(); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(Object[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (Object element : array) { hash = MULTIPLIER * hash + nullSafeHashCode(element); } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(boolean[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (boolean element : array) { hash = MULTIPLIER * hash + Boolean.hashCode(element); } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(byte[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (byte element : array) { hash = MULTIPLIER * hash + element; } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(char[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (char element : array) { hash = MULTIPLIER * hash + element; } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(double[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (double element : array) { hash = MULTIPLIER * hash + Double.hashCode(element); } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(float[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (float element : array) { hash = MULTIPLIER * hash + Float.hashCode(element); } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(int[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (int element : array) { hash = MULTIPLIER * hash + element; } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(long[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (long element : array) { hash = MULTIPLIER * hash + Long.hashCode(element); } return hash; } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. */ public static int nullSafeHashCode(short[] array) { if (array == null) { return 0; } int hash = INITIAL_HASH; for (short element : array) { hash = MULTIPLIER * hash + element; } return hash; } /** * Determine if the given objects are equal, returning {@code true} if * both are {@code null} or {@code false} if only one is {@code null}. *

Compares arrays with {@code Arrays.equals}, performing an equality * check based on the array elements rather than the array reference. * @param o1 first Object to compare * @param o2 second Object to compare * @return whether the given objects are equal * @see Object#equals(Object) * @see java.util.Arrays#equals */ public static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) { return true; } if (o1 == null || o2 == null) { return false; } if (o1.equals(o2)) { return true; } if (o1.getClass().isArray() && o2.getClass().isArray()) { return arrayEquals(o1, o2); } return false; } /** * Compare the given arrays with {@code Arrays.equals}, performing an equality * check based on the array elements rather than the array reference. * @param o1 first array to compare * @param o2 second array to compare * @return whether the given objects are equal * @see #nullSafeEquals(Object, Object) * @see java.util.Arrays#equals */ private static boolean arrayEquals(Object o1, Object o2) { if (o1 instanceof Object[] && o2 instanceof Object[]) { return Arrays.equals((Object[]) o1, (Object[]) o2); } if (o1 instanceof boolean[] && o2 instanceof boolean[]) { return Arrays.equals((boolean[]) o1, (boolean[]) o2); } if (o1 instanceof byte[] && o2 instanceof byte[]) { return Arrays.equals((byte[]) o1, (byte[]) o2); } if (o1 instanceof char[] && o2 instanceof char[]) { return Arrays.equals((char[]) o1, (char[]) o2); } if (o1 instanceof double[] && o2 instanceof double[]) { return Arrays.equals((double[]) o1, (double[]) o2); } if (o1 instanceof float[] && o2 instanceof float[]) { return Arrays.equals((float[]) o1, (float[]) o2); } if (o1 instanceof int[] && o2 instanceof int[]) { return Arrays.equals((int[]) o1, (int[]) o2); } if (o1 instanceof long[] && o2 instanceof long[]) { return Arrays.equals((long[]) o1, (long[]) o2); } if (o1 instanceof short[] && o2 instanceof short[]) { return Arrays.equals((short[]) o1, (short[]) o2); } return false; } /************************ Field about***********************/ /** * Attempt to find a {@link Field field} on the supplied {@link Class} with the * supplied {@code name}. Searches all super-classes up to {@link Object}. * * @param clazz the class to introspect * @param name the name of the field * @return the corresponding Field object, or {@code null} if not found */ public static Field findField(Class clazz, String name) { return findField(clazz, name, null); } /** * Get the field represented by the supplied {@link Field field object} on the * specified {@link Object target object}. In accordance with {@link Field#get(Object)} * semantics, the returned value is automatically wrapped if the underlying field * has a primitive type. * @param * * @param name the field name to get * @param target the target object from which to get the field * @return the field's current value */ public static T getFieldValue(Object target, String name, Class type) { Field field = findField(target.getClass(), name); if (null == field) { return null; } try { makeAccessible(field); return type.cast(field.get(target)); } catch (IllegalAccessException ex) { handleReflectionException(ex); } throw new IllegalStateException("Should never get here"); } public static void setFieldValue(Object target, String name, Class type, Object value) { Field field = findField(target.getClass(), name); if (null == field) { return; } try { makeAccessible(field); field.set(target, value); return; } catch (IllegalAccessException ex) { handleReflectionException(ex); } throw new IllegalStateException("Should never get here"); } /** * Make the given field accessible, explicitly setting it accessible if * necessary. The {@code setAccessible(true)} method is only called when * actually necessary, to avoid unnecessary conflicts with a JVM SecurityManager (if active). * * @param field the field to make accessible * @see java.lang.reflect.Field#setAccessible */ public static void makeAccessible(Field field) { if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { field.setAccessible(true); } } /** * Attempt to find a {@link Field field} on the supplied {@link Class} with the * supplied {@code name} and/or {@link Class type}. Searches all super-classes up to {@link Object}. * * @param clazz the class to introspect * @param name the name of the field (may be {@code null} if type is specified) * @param type the type of the field (may be {@code null} if name is specified) * @return the corresponding Field object, or {@code null} if not found */ public static Field findField(Class clazz, String name, Class type) { assertNotNull(clazz, "Class must not be null"); assertIsTrue(name != null || type != null, () -> "Either name or type of the field must be specified"); Class searchType = clazz; while (Object.class != searchType && searchType != null) { Field[] fields = getDeclaredFields(searchType); for (Field field : fields) { if ((name == null || name.equals(field.getName())) && (type == null || type.equals(field.getType()))) { return field; } } searchType = searchType.getSuperclass(); } return null; } private static Field[] getDeclaredFields(Class clazz) { assertNotNull(clazz, "Class must not be null"); SoftReference fieldsRef = LOCAL_FIELDS.get(clazz); if (fieldsRef == null) { try { Field[] declaredFields = clazz.getDeclaredFields(); fieldsRef = new SoftReference<>((declaredFields.length == 0 ? EMPTY_FIELD_ARRAY : declaredFields)); LOCAL_FIELDS.put(clazz, fieldsRef); } catch (Throwable ex) { throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() + "] from ClassLoader [" + clazz.getClassLoader() + "]", ex); } } return fieldsRef.get(); } /************************ Method about***********************/ /** * Attempt to find a {@link Method} on the supplied class with the supplied name * and no parameters. Searches all superclasses up to {@code Object}. *

Returns {@code null} if no {@link Method} can be found. * @param clazz the class to introspect * @param name the name of the method * @return the Method object, or {@code null} if none found */ public static Method findMethod(Class clazz, String name) { return findMethod(clazz, name, new Class[0]); } /** * Attempt to find a {@link Method} on the supplied class with the supplied name * and parameter types. Searches all superclasses up to {@code Object}. *

Returns {@code null} if no {@link Method} can be found. * @param clazz the class to introspect * @param name the name of the method * @param argTypes the parameter types of the method * (may be {@code null} to indicate any signature) * @return the Method object, or {@code null} if none found */ public static Method findMethod(Class clazz, String name, Class... argTypes) { assertNotNull(clazz, "Class must not be null"); assertNotNull(name, "Method name must not be null"); Class searchType = clazz; while (searchType != null) { Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType)); for (Method method : methods) { if (name.equals(method.getName()) && (argTypes == null || Arrays.equals(argTypes, method.getParameterTypes()))) { return method; } } searchType = searchType.getSuperclass(); } return null; } /** * This variant retrieves {@link Class#getDeclaredMethods()} from a local cache * in order to avoid the JVM's SecurityManager check and defensive array copying. * In addition, it also includes Java 8 default methods from locally implemented * interfaces, since those are effectively to be treated just like declared methods. * @param clazz the class to introspect * @return the cached array of methods * @throws IllegalStateException if introspection fails * @see Class#getDeclaredMethods() */ private static Method[] getDeclaredMethods(Class clazz) { assertNotNull(clazz, "Class must not be null"); SoftReference methodRef = LOCAL_METHODS.get(clazz); if (methodRef == null) { try { Method[] declaredMethods = clazz.getDeclaredMethods(); List defaultMethods = findConcreteMethodsOnInterfaces(clazz); Method[] result = declaredMethods; if (defaultMethods != null) { result = new Method[declaredMethods.length + defaultMethods.size()]; System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length); int index = declaredMethods.length; for (Method defaultMethod : defaultMethods) { result[index] = defaultMethod; index++; } } methodRef = new SoftReference((result.length == 0 ? EMPTY_METHOD_ARRAY : result)); LOCAL_METHODS.put(clazz, methodRef); } catch (Throwable ex) { throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() + "] from ClassLoader [" + clazz.getClassLoader() + "]", ex); } } return methodRef.get(); } private static List findConcreteMethodsOnInterfaces(Class clazz) { List result = null; for (Class ifc : clazz.getInterfaces()) { for (Method ifcMethod : ifc.getMethods()) { if (!Modifier.isAbstract(ifcMethod.getModifiers())) { if (result == null) { result = new ArrayList<>(); } result.add(ifcMethod); } } } return result; } public static void makeAccessible(Method method) { if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { method.setAccessible(true); } } public static Object invokeMethod(Object target, String methodName) { return invokeMethod(target, methodName, new Class[] {}); } public static Object invokeSuperMethod(Object target, String methodName) { return invokeSuperMethod(target, methodName, new Class[]{}); } public static Object invokeMethod(Object target, String methodName, Class argType, Object arg) { return invokeMethod(target, methodName, new Class[] { argType }, ((Object) arg)); } public static Object invokeMethod(Object target, String methodName, Class[] argTypes, Object... args) { assertNotNull(target, "Object must not be null"); Method method = findMethod(target.getClass(), methodName, argTypes); if (method == null) { return null; } try { makeAccessible(method); return method.invoke(target, args); } catch (Exception ex) { handleReflectionException(ex); } throw new IllegalStateException("Should never get here"); } public static Object invokeSuperMethod(Object target, String methodName, Class[] argTypes, Object... args) { assertNotNull(target, "Object must not be null"); Method method = findMethod(target.getClass().getSuperclass(), methodName, argTypes); if (method == null) { return null; } try { makeAccessible(method); return method.invoke(target, args); } catch (Exception ex) { handleReflectionException(ex); } throw new IllegalStateException("Should never get here"); } private static void handleReflectionException(Exception ex) { if (ex instanceof NoSuchMethodException) { throw new IllegalStateException("Method not found: " + ex.getMessage()); } if (ex instanceof IllegalAccessException) { throw new IllegalStateException("Could not access method or field: " + ex.getMessage()); } if (ex instanceof InvocationTargetException) { rethrowRuntimeException(((InvocationTargetException) ex).getTargetException()); } if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } throw new UndeclaredThrowableException(ex); } private static void rethrowRuntimeException(Throwable ex) { if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } if (ex instanceof Error) { throw (Error) ex; } throw new UndeclaredThrowableException(ex); } public static class MutableArray { private final ArrayList list; @SuppressWarnings("unchecked") MutableArray(T... initialElements) { this.list = new ArrayList(Arrays.asList(initialElements)); } public MutableArray add(boolean executed, Supplier supplier) { if (executed) { this.list.add(supplier.get()); } return this; } public MutableArray replace(int index, T e) { this.list.set(index, e); return this; } public Object[] toArray() { return this.list.toArray(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy