added the getters

This commit is contained in:
Shautvast 2023-09-03 11:29:04 +02:00
parent 021304a5d8
commit fbfd8d5e93
20 changed files with 440 additions and 176 deletions

View file

@ -2,11 +2,17 @@ package com.github.shautvast.reflective.array;
import com.github.shautvast.reflective.array.base.*;
import java.lang.reflect.Array;
/**
* Public interface for dynamically working with arrays (create, set and get operations)
* <p>
* Drop in replacement for java.lang.reflect.Array
*/
public class ArrayFactory {
public final class ArrayFactory {
private ArrayFactory() {
}
/**
* Creates a new array of the specified type and dimensions
@ -27,7 +33,18 @@ public class ArrayFactory {
* @param value the value to set
*/
public static void set(Object array, int index, Object value) {
ArrayHandlerFactory.getSetterInstance(ObjectArraySetter.class, typeChecked(array)).set(array, index, value);
ArrayHandlerFactory.getAccessorInstance(ObjectArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a Object value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static Object get(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(ObjectArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -37,8 +54,19 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, int value) {
ArrayHandlerFactory.getSetterInstance(IntArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setInt(Object array, int index, int value) {
ArrayHandlerFactory.getAccessorInstance(IntArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets an int value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static int getInt(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(IntArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -48,8 +76,19 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, byte value) {
ArrayHandlerFactory.getSetterInstance(ByteArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setByte(Object array, int index, byte value) {
ArrayHandlerFactory.getAccessorInstance(ByteArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a byte value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static byte getByte(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(ByteArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -59,8 +98,19 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, short value) {
ArrayHandlerFactory.getSetterInstance(ShortArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setShort(Object array, int index, short value) {
ArrayHandlerFactory.getAccessorInstance(ShortArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a short value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static short getShort(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(ShortArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -70,8 +120,19 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, long value) {
ArrayHandlerFactory.getSetterInstance(LongArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setLong(Object array, int index, long value) {
ArrayHandlerFactory.getAccessorInstance(LongArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a long value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static long getLong(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(LongArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -81,8 +142,19 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, float value) {
ArrayHandlerFactory.getSetterInstance(FloatArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setFloat(Object array, int index, float value) {
ArrayHandlerFactory.getAccessorInstance(FloatArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a float value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static float getFloat(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(FloatArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
@ -92,26 +164,77 @@ public class ArrayFactory {
* @param index the array index
* @param value the value to set
*/
public static void set(Object array, int index, double value) {
ArrayHandlerFactory.getSetterInstance(DoubleArraySetter.class, typeChecked(array)).set(array, index, value);
public static void setDouble(Object array, int index, double value) {
ArrayHandlerFactory.getAccessorInstance(DoubleArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
public static void set(Object array, int index, char value) {
ArrayHandlerFactory.getSetterInstance(CharArraySetter.class, typeChecked(array)).set(array, index, value);
/**
* Gets a double value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static double getDouble(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(DoubleArrayAccessor.class, typeChecked(array)).get(array, index);
}
public static void set(Object array, int index, boolean value) {
ArrayHandlerFactory.getSetterInstance(BooleanArraySetter.class, typeChecked(array)).set(array, index, value);
/**
* Sets a char value on an array
*
* @param array the array on which the value is set
* @param index the array index
* @param value the value to set
*/
public static void setChar(Object array, int index, char value) {
ArrayHandlerFactory.getAccessorInstance(CharArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a char value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static char getChar(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(CharArrayAccessor.class, typeChecked(array)).get(array, index);
}
/**
* Sets a boolean value on an array
*
* @param array the array on which the value is set
* @param index the array index
* @param value the value to set
*/
public static void setBoolean(Object array, int index, boolean value) {
ArrayHandlerFactory.getAccessorInstance(BooleanArrayAccessor.class, typeChecked(array)).set(array, index, value);
}
/**
* Gets a boolean value from an array
*
* @param array the array to access
* @param index
* @return the value of the array at the index
*/
public static boolean getBoolean(Object array, int index) {
return ArrayHandlerFactory.getAccessorInstance(BooleanArrayAccessor.class, typeChecked(array)).get(array, index);
}
/*
* Only checks if object is an array, not the type of that array. TODO
*/
private static Class<?> typeChecked(Object array) {
if (array == null) {
throw new NullPointerException("Argument is null");
}
Class<?> arrayType = array.getClass();
if (!arrayType.isArray()) {
throw new IllegalArgumentException("This is not an array");
throw new IllegalArgumentException("Argument is not an array");
}
return arrayType;
}
}

View file

@ -1,8 +1,8 @@
package com.github.shautvast.reflective.array;
import com.github.shautvast.reflective.array.base.ArrayCreator;
import com.github.shautvast.reflective.array.base.ArraySetter;
import com.github.shautvast.reflective.array.base.ObjectArraySetter;
import com.github.shautvast.reflective.array.base.ArrayAccessor;
import com.github.shautvast.reflective.array.base.ObjectArrayAccessor;
import com.github.shautvast.reflective.java.ASM;
import com.github.shautvast.reflective.java.ByteClassLoader;
import com.github.shautvast.reflective.java.Java;
@ -21,45 +21,38 @@ class ArrayHandlerFactory {
/* cache for the compiled creator classes */
private static final Map<String, ArrayCreator> creatorCache = new ConcurrentHashMap<>();
/* Cache for the compiled setter classes.
* The outer Map contains the ArraySetter type (some primitive or Object Setter)
* That maps to the concrete calculated ArraySetter instance name which maps to the instance itself.
/* Cache for the compiled accessor classes.
* The outer Map contains the ArrayAccessor type (some primitive or Object Accessor)
* That maps to the concrete calculated ArrayAccessor instance name which maps to the instance itself.
* TODO see if this can be optimized
*/
private static final Map<Class<? extends ArraySetter>, Map<String, Object>> setterCache = new ConcurrentHashMap<>();
private static final Map<Class<? extends ArrayAccessor>, Map<String, Object>> accessorCache = new ConcurrentHashMap<>();
/*
* generic method for creating array setters (primitives and objects)
* generic method for creating array accessors (primitives and objects)
*/
@SuppressWarnings("unchecked")
static <T extends ArraySetter> T getSetterInstance(Class<T> setterBaseType, Class<?> arrayType) {
static <T extends ArrayAccessor> T getAccessorInstance(Class<T> accessorBaseType, Class<?> arrayType) {
String arrayTypeName = Java.internalName(arrayType);
String syntheticClassName = "com/shautvast/reflective/array/ArraySetter_"
+ javaName(arrayTypeName) + Java.getNumDimensions(arrayType);
String syntheticClassName = "com/shautvast/reflective/array/ArrayAccessor_"
+ Java.javaName(arrayTypeName) + Java.getNumDimensions(arrayType);
return (T) setterCache.computeIfAbsent(setterBaseType, k -> new ConcurrentHashMap<>()).
return (T) accessorCache.computeIfAbsent(accessorBaseType, k -> new ConcurrentHashMap<>()).
computeIfAbsent(syntheticClassName,
k -> ArrayHandlerFactory.createSyntheticArraySetter(setterBaseType, arrayTypeName, syntheticClassName));
k -> ArrayHandlerFactory.createSyntheticArrayAccessor(accessorBaseType, arrayTypeName, syntheticClassName));
}
/* creates an instance of an ArrayCreator of the specified type */
static ArrayCreator getCreatorInstance(Class<?> elementType, int... dimensions) {
String elementTypeName = Java.internalName(elementType);
String syntheticClassName = "com/shautvast/reflective/array/ArrayCreator_"
+ javaName(elementTypeName) + dimensions.length;
+ Java.javaName(elementTypeName) + dimensions.length;
return creatorCache.computeIfAbsent(syntheticClassName,
k -> ArrayHandlerFactory.createSyntheticArrayCreator(elementTypeName, syntheticClassName, dimensions));
}
/* strips all disallowed characters from a classname */
private static String javaName(String arrayTypeName) {
return arrayTypeName
.replaceAll("[/.\\[;]", "")
.toLowerCase();
}
/* Creates the ASM ClassNode for an ArrayCreator */
static ArrayCreator createSyntheticArrayCreator(String elementType, String name, int... dimensions) {
ClassNode classNode = ASM.createDefaultClassNode(name, Java.internalName(ArrayCreator.class));
@ -84,10 +77,11 @@ class ArrayHandlerFactory {
}
}
/* Creates the ASM ClassNode for an ArraySetter */
static <T> T createSyntheticArraySetter(Class<T> setterType, String arrayType, String name) {
ClassNode classNode = ASM.createDefaultClassNode(name, Java.internalName(setterType));
classNode.methods.add(createSetMethodNode(setterType, arrayType));
/* Creates the ASM ClassNode for an ArrayAccessor */
static <T> T createSyntheticArrayAccessor(Class<T> accessorType, String arrayType, String name) {
ClassNode classNode = ASM.createDefaultClassNode(name, Java.internalName(accessorType));
classNode.methods.add(createSetMethodNode(accessorType, arrayType));
classNode.methods.add(createGetMethodNode(accessorType, arrayType));
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
classNode.accept(classWriter);
@ -102,7 +96,7 @@ class ArrayHandlerFactory {
ByteClassLoader.INSTANCE.addClass(classNode.name, byteArray);
try {
return setterType.cast(ByteClassLoader.INSTANCE.loadClass(classNode.name).getConstructor().newInstance());
return accessorType.cast(ByteClassLoader.INSTANCE.loadClass(classNode.name).getConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -119,17 +113,17 @@ class ArrayHandlerFactory {
return methodNode;
}
/* Creates the set method for ArraySetter classes */
private static MethodNode createSetMethodNode(Class<?> setterType, String arrayType) {
/* Creates the set method for ArrayAccessor classes */
private static MethodNode createSetMethodNode(Class<?> accessorType, String arrayType) {
String elementType;
if (setterType == ObjectArraySetter.class) {
if (accessorType == ObjectArrayAccessor.class) {
elementType = "Ljava/lang/Object;";
} else {
elementType = arrayType.substring(1);
}
MethodNode methodNode = new MethodNode(ACC_PUBLIC,
"set", "(Ljava/lang/Object;I" + elementType + ")V", null, null);
int[] opcodes = getInstructions(elementType);
int[] opcodes = arrayStoreInstructions(elementType);
InsnList insns = methodNode.instructions;
insns.add(new VarInsnNode(ALOAD, 1));
insns.add(new TypeInsnNode(CHECKCAST, arrayType));
@ -141,14 +135,34 @@ class ArrayHandlerFactory {
return methodNode;
}
private static MethodNode createGetMethodNode(Class<?> accessorType, String arrayType) {
String elementType;
if (accessorType == ObjectArrayAccessor.class) {
elementType = "Ljava/lang/Object;";
} else {
elementType = arrayType.substring(1);
}
MethodNode methodNode = new MethodNode(ACC_PUBLIC,
"get", "(Ljava/lang/Object;I)" + elementType, null, null);
InsnList insns = methodNode.instructions;
int[] opcodes = arrayLoadAndReturnInstructions(elementType);
insns.add(new VarInsnNode(ALOAD, 1));
insns.add(new TypeInsnNode(CHECKCAST, arrayType));
insns.add(new VarInsnNode(ILOAD, 2));
insns.add(new InsnNode(opcodes[0]));
insns.add(new InsnNode(opcodes[1]));
return methodNode;
}
/*
* gets the pair of appropriate load (type) and store (array of type) instructions
*/
private static int[] getInstructions(String type) {
private static int[] arrayStoreInstructions(String type) {
switch (type) {
case "B":
case "Z":
return new int[]{ILOAD, BASTORE}; // load int, store byte??
return new int[]{ILOAD, BASTORE};
case "S":
return new int[]{ILOAD, SASTORE};
case "I":
@ -165,4 +179,29 @@ class ArrayHandlerFactory {
return new int[]{ALOAD, AASTORE};
}
}
/*
* gets the pair of appropriate load (type) and store (array of type) instructions
*/
private static int[] arrayLoadAndReturnInstructions(String type) {
switch (type) {
case "B":
case "Z":
return new int[]{BALOAD, IRETURN};
case "I":
return new int[]{IALOAD, IRETURN};
case "S":
return new int[]{SALOAD, IRETURN};
case "C":
return new int[]{CALOAD, IRETURN};
case "J":
return new int[]{LALOAD, LRETURN};
case "F":
return new int[]{FALOAD, FRETURN};
case "D":
return new int[]{DALOAD, DRETURN};
default:
return new int[]{AALOAD, ARETURN};
}
}
}

View file

@ -3,5 +3,5 @@ package com.github.shautvast.reflective.array.base;
/**
* Empty interface because you can't be generic over primitives in Java
*/
public interface ArraySetter {
public interface ArrayAccessor {
}

View file

@ -0,0 +1,6 @@
package com.github.shautvast.reflective.array.base;
public abstract class BooleanArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, boolean value);
public abstract boolean get(Object array, int index);
}

View file

@ -1,5 +0,0 @@
package com.github.shautvast.reflective.array.base;
public abstract class BooleanArraySetter implements ArraySetter {
public abstract void set(Object array, int index, boolean value);
}

View file

@ -1,6 +1,8 @@
package com.github.shautvast.reflective.array.base;
public abstract class ByteArraySetter implements ArraySetter {
public abstract class ByteArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, byte value);
public abstract byte get(Object array, int index);
}

View file

@ -1,6 +1,7 @@
package com.github.shautvast.reflective.array.base;
public abstract class CharArraySetter implements ArraySetter {
public abstract class CharArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, char value);
public abstract char get(Object array, int index);
}

View file

@ -0,0 +1,7 @@
package com.github.shautvast.reflective.array.base;
public abstract class DoubleArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, double value);
public abstract double get(Object array, int index);
}

View file

@ -1,6 +0,0 @@
package com.github.shautvast.reflective.array.base;
public abstract class DoubleArraySetter implements ArraySetter {
public abstract void set(Object array, int index, double value);
}

View file

@ -0,0 +1,8 @@
package com.github.shautvast.reflective.array.base;
public abstract class FloatArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, float value);
public abstract float get(Object array, int index);
}

View file

@ -1,6 +0,0 @@
package com.github.shautvast.reflective.array.base;
public abstract class FloatArraySetter implements ArraySetter {
public abstract void set(Object array, int index, float value);
}

View file

@ -1,5 +1,7 @@
package com.github.shautvast.reflective.array.base;
public abstract class IntArraySetter implements ArraySetter {
public abstract class IntArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, int value);
public abstract int get(Object array, int index);
}

View file

@ -1,6 +1,8 @@
package com.github.shautvast.reflective.array.base;
public abstract class LongArraySetter implements ArraySetter {
public abstract class LongArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, long value);
public abstract long get(Object array, int index);
}

View file

@ -0,0 +1,6 @@
package com.github.shautvast.reflective.array.base;
public abstract class ObjectArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, Object value);
public abstract Object get(Object array, int index);
}

View file

@ -1,5 +0,0 @@
package com.github.shautvast.reflective.array.base;
public abstract class ObjectArraySetter implements ArraySetter {
public abstract void set(Object array, int index, Object value);
}

View file

@ -0,0 +1,8 @@
package com.github.shautvast.reflective.array.base;
public abstract class ShortArrayAccessor implements ArrayAccessor {
public abstract void set(Object array, int index, short value);
public abstract short get(Object array, int index);
}

View file

@ -1,6 +0,0 @@
package com.github.shautvast.reflective.array.base;
public abstract class ShortArraySetter implements ArraySetter {
public abstract void set(Object array, int index, short value);
}

View file

@ -156,6 +156,13 @@ public class Java {
}
}
/* strips all disallowed characters from a classname */
public static String javaName(String arrayTypeName) {
return arrayTypeName
.replaceAll("[/.\\[;]", "")
.toLowerCase();
}
public static String mapPrimitiveOrArrayName(String type) {
switch (type) {
case "byte":

View file

@ -0,0 +1,174 @@
package com.github.shautvast.reflective.array;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ArrayFactoryTest {
@Test
void testCreate1DimShortArray() {
Object o = ArrayFactory.newInstance(short.class, 1);
assertTrue(o instanceof short[]);
}
@Test
void testCreate2DimIntArray() {
int[][] ints = (int[][]) ArrayFactory.newInstance(int[].class, 1);
assertEquals(1, ints.length);
ints[0] = new int[1]; // will fail if array is not correctly created
assertEquals(1, ints[0].length);
}
@Test
void testCreate3DimStringArray() {
String[][][] array = (String[][][]) ArrayFactory.newInstance(String.class, 6, 7, 8);
assertEquals(6, array.length);
assertEquals(7, array[0].length);
assertEquals(8, array[0][0].length);
}
@Test
void testSetObject() {
String[] strings = new String[1];
ArrayFactory.set(strings, 0, "helloworld");
assertArrayEquals(new String[]{"helloworld"}, strings);
}
@Test
void testSetInt() {
int[] ints = new int[1];
ArrayFactory.setInt(ints, 0, 11);
assertArrayEquals(new int[]{11}, ints);
}
@Test
void testSetByte() {
byte[] bytes = new byte[1];
ArrayFactory.setByte(bytes, 0, (byte) 11);
assertArrayEquals(new byte[]{11}, bytes);
}
@Test
void testSetShort() {
short[] shorts = new short[1];
ArrayFactory.setShort(shorts, 0, (short) 11);
assertArrayEquals(new short[]{11}, shorts);
}
@Test
void testSetLong() {
long[] longs = new long[1];
ArrayFactory.setLong(longs, 0, 11L);
assertArrayEquals(new long[]{11}, longs);
}
@Test
void testSetFloat() {
float[] floats = new float[1];
ArrayFactory.setFloat(floats, 0, 11.1F);
assertArrayEquals(new float[]{11.1F}, floats);
}
@Test
void testSetDouble() {
double[] doubles = new double[1];
ArrayFactory.setDouble(doubles, 0, 11.1D);
assertArrayEquals(new double[]{11.1D}, doubles);
}
@Test
void testSetBoolean() {
boolean[] booleans = new boolean[]{false};
ArrayFactory.setBoolean(booleans, 0, true);
assertArrayEquals(new boolean[]{true}, booleans);
}
@Test
void testSetChar() {
char[] chars = new char[]{'C'};
ArrayFactory.setChar(chars, 0, 'D');
assertArrayEquals(new char[]{'D'}, chars);
}
@Test
void testGetFromObjectArray() {
String[] strings = new String[]{"helloworld"};
Object o = ArrayFactory.get(strings, 0);
assertTrue(o instanceof String);
String string = (String) o;
assertEquals("helloworld", string);
}
@Test
void testGetFromByteArray() {
byte[] bytes = new byte[]{17};
byte b = ArrayFactory.getByte(bytes, 0);
assertEquals(17, b);
}
@Test
void testGetFromShortArray() {
short[] shorts = new short[]{17};
short s = ArrayFactory.getShort(shorts, 0);
assertEquals(17, s);
}
@Test
void testGetFromIntArray() {
int[] ints = new int[]{17};
int i = ArrayFactory.getInt(ints, 0);
assertEquals(17, i);
}
@Test
void testGetFromLongArray() {
long[] longs = new long[]{17};
long l = ArrayFactory.getLong(longs, 0);
assertEquals(17, l);
}
@Test
void testGetFromCharArray() {
char[] chars = new char[]{17};
char c = ArrayFactory.getChar(chars, 0);
assertEquals(17, c);
}
@Test
void testGetFromBooleanArray() {
boolean[] booleans = new boolean[]{true};
boolean b = ArrayFactory.getBoolean(booleans, 0);
assertEquals(true, b);
}
@Test
void testGetFromFloatArray() {
float[] floats = new float[]{17.5F};
float f = ArrayFactory.getFloat(floats, 0);
assertEquals(17.5, f);
}
@Test
void testGetFromDoubleArray() {
double[] doubles = new double[]{17.5F};
double d = ArrayFactory.getDouble(doubles, 0);
assertEquals(17.5, d);
}
@Test
void arrayIndexOutOfBoundsException() {
double[] doubles = new double[]{};
assertThrows(ArrayIndexOutOfBoundsException.class, () -> ArrayFactory.getDouble(doubles, 0));
}
@Test
void notAnArray() {
assertThrows(IllegalArgumentException.class, () -> ArrayFactory.get("foo", 0));
}
@Test
void arrayIsNull() {
assertThrows(NullPointerException.class, () -> ArrayFactory.get(null, 0));
}
}

View file

@ -1,93 +0,0 @@
package com.github.shautvast.reflective.array;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ArraysTest {
@Test
void testCreate1DimShortArray() {
Object o = ArrayFactory.newInstance(short.class, 1);
assertTrue(o instanceof short[]);
}
@Test
void testCreate2DimIntArray() {
int[][] ints = (int[][]) ArrayFactory.newInstance(int[].class, 1);
assertEquals(1, ints.length);
ints[0] = new int[1]; // will fail if array is not correctly created
assertEquals(1, ints[0].length);
}
@Test
void testCreate3DimStringArray() {
String[][][] array = (String[][][]) ArrayFactory.newInstance(String.class, 6, 7, 8);
assertEquals(6, array.length);
assertEquals(7, array[0].length);
assertEquals(8, array[0][0].length);
}
@Test
void testSetObject() {
String[] strings = new String[1];
ArrayFactory.set(strings, 0, "helloworld");
assertArrayEquals(new String[]{"helloworld"}, strings);
}
@Test
void testSetInt() {
int[] ints = new int[1];
ArrayFactory.set(ints, 0, 11);
assertArrayEquals(new int[]{11}, ints);
}
@Test
void testSetByte() {
byte[] bytes = new byte[1];
ArrayFactory.set(bytes, 0, (byte) 11);
assertArrayEquals(new byte[]{11}, bytes);
}
@Test
void testSetShort() {
short[] shorts = new short[1];
ArrayFactory.set(shorts, 0, (short) 11);
assertArrayEquals(new short[]{11}, shorts);
}
@Test
void testSetLong() {
long[] longs = new long[1];
ArrayFactory.set(longs, 0, 11L);
assertArrayEquals(new long[]{11}, longs);
}
@Test
void testSetFloat() {
float[] floats = new float[1];
ArrayFactory.set(floats, 0, 11.1F);
assertArrayEquals(new float[]{11.1F}, floats);
}
@Test
void testSetDouble() {
double[] doubles = new double[1];
ArrayFactory.set(doubles, 0, 11.1D);
assertArrayEquals(new double[]{11.1D}, doubles);
}
@Test
void testSetBoolean() {
boolean[] booleans = new boolean[]{false};
ArrayFactory.set(booleans, 0, true);
assertArrayEquals(new boolean[]{true}, booleans);
}
@Test
void testSetChar() {
char[] chars = new char[]{'C'};
ArrayFactory.set(chars, 0, 'D');
assertArrayEquals(new char[]{'D'}, chars);
}
}