diff --git a/src/main/java/com/github/shautvast/reflective/array/ArrayFactory.java b/src/main/java/com/github/shautvast/reflective/array/ArrayFactory.java
index 6763dff..3af44a9 100644
--- a/src/main/java/com/github/shautvast/reflective/array/ArrayFactory.java
+++ b/src/main/java/com/github/shautvast/reflective/array/ArrayFactory.java
@@ -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)
+ *
+ * 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;
}
+
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/ArrayHandlerFactory.java b/src/main/java/com/github/shautvast/reflective/array/ArrayHandlerFactory.java
index 1ca274a..446b773 100644
--- a/src/main/java/com/github/shautvast/reflective/array/ArrayHandlerFactory.java
+++ b/src/main/java/com/github/shautvast/reflective/array/ArrayHandlerFactory.java
@@ -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 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, Map> setterCache = new ConcurrentHashMap<>();
+ private static final Map, Map> 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 getSetterInstance(Class setterBaseType, Class> arrayType) {
+ static T getAccessorInstance(Class 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 createSyntheticArraySetter(Class 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 createSyntheticArrayAccessor(Class 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};
+ }
+ }
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/ArrayAccessor.java
similarity index 80%
rename from src/main/java/com/github/shautvast/reflective/array/base/ArraySetter.java
rename to src/main/java/com/github/shautvast/reflective/array/base/ArrayAccessor.java
index ca4ae27..b7e35b2 100644
--- a/src/main/java/com/github/shautvast/reflective/array/base/ArraySetter.java
+++ b/src/main/java/com/github/shautvast/reflective/array/base/ArrayAccessor.java
@@ -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 {
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/BooleanArrayAccessor.java b/src/main/java/com/github/shautvast/reflective/array/base/BooleanArrayAccessor.java
new file mode 100644
index 0000000..088a96f
--- /dev/null
+++ b/src/main/java/com/github/shautvast/reflective/array/base/BooleanArrayAccessor.java
@@ -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);
+}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/BooleanArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/BooleanArraySetter.java
deleted file mode 100644
index fef0909..0000000
--- a/src/main/java/com/github/shautvast/reflective/array/base/BooleanArraySetter.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ByteArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/ByteArrayAccessor.java
similarity index 50%
rename from src/main/java/com/github/shautvast/reflective/array/base/ByteArraySetter.java
rename to src/main/java/com/github/shautvast/reflective/array/base/ByteArrayAccessor.java
index 06796b0..dd66a95 100644
--- a/src/main/java/com/github/shautvast/reflective/array/base/ByteArraySetter.java
+++ b/src/main/java/com/github/shautvast/reflective/array/base/ByteArrayAccessor.java
@@ -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);
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/CharArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/CharArrayAccessor.java
similarity index 50%
rename from src/main/java/com/github/shautvast/reflective/array/base/CharArraySetter.java
rename to src/main/java/com/github/shautvast/reflective/array/base/CharArrayAccessor.java
index 8453275..2245368 100644
--- a/src/main/java/com/github/shautvast/reflective/array/base/CharArraySetter.java
+++ b/src/main/java/com/github/shautvast/reflective/array/base/CharArrayAccessor.java
@@ -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);
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/DoubleArrayAccessor.java b/src/main/java/com/github/shautvast/reflective/array/base/DoubleArrayAccessor.java
new file mode 100644
index 0000000..5820ac1
--- /dev/null
+++ b/src/main/java/com/github/shautvast/reflective/array/base/DoubleArrayAccessor.java
@@ -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);
+}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/DoubleArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/DoubleArraySetter.java
deleted file mode 100644
index a4b1275..0000000
--- a/src/main/java/com/github/shautvast/reflective/array/base/DoubleArraySetter.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/FloatArrayAccessor.java b/src/main/java/com/github/shautvast/reflective/array/base/FloatArrayAccessor.java
new file mode 100644
index 0000000..2fd3fa6
--- /dev/null
+++ b/src/main/java/com/github/shautvast/reflective/array/base/FloatArrayAccessor.java
@@ -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);
+}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/FloatArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/FloatArraySetter.java
deleted file mode 100644
index f279048..0000000
--- a/src/main/java/com/github/shautvast/reflective/array/base/FloatArraySetter.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/IntArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/IntArrayAccessor.java
similarity index 50%
rename from src/main/java/com/github/shautvast/reflective/array/base/IntArraySetter.java
rename to src/main/java/com/github/shautvast/reflective/array/base/IntArrayAccessor.java
index c04d0a9..89f8aa3 100644
--- a/src/main/java/com/github/shautvast/reflective/array/base/IntArraySetter.java
+++ b/src/main/java/com/github/shautvast/reflective/array/base/IntArrayAccessor.java
@@ -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);
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/LongArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/LongArrayAccessor.java
similarity index 50%
rename from src/main/java/com/github/shautvast/reflective/array/base/LongArraySetter.java
rename to src/main/java/com/github/shautvast/reflective/array/base/LongArrayAccessor.java
index ecf8309..37b2a57 100644
--- a/src/main/java/com/github/shautvast/reflective/array/base/LongArraySetter.java
+++ b/src/main/java/com/github/shautvast/reflective/array/base/LongArrayAccessor.java
@@ -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);
}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ObjectArrayAccessor.java b/src/main/java/com/github/shautvast/reflective/array/base/ObjectArrayAccessor.java
new file mode 100644
index 0000000..30f2838
--- /dev/null
+++ b/src/main/java/com/github/shautvast/reflective/array/base/ObjectArrayAccessor.java
@@ -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);
+}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ObjectArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/ObjectArraySetter.java
deleted file mode 100644
index f7f71fb..0000000
--- a/src/main/java/com/github/shautvast/reflective/array/base/ObjectArraySetter.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ShortArrayAccessor.java b/src/main/java/com/github/shautvast/reflective/array/base/ShortArrayAccessor.java
new file mode 100644
index 0000000..1b17c15
--- /dev/null
+++ b/src/main/java/com/github/shautvast/reflective/array/base/ShortArrayAccessor.java
@@ -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);
+}
diff --git a/src/main/java/com/github/shautvast/reflective/array/base/ShortArraySetter.java b/src/main/java/com/github/shautvast/reflective/array/base/ShortArraySetter.java
deleted file mode 100644
index 3be5d80..0000000
--- a/src/main/java/com/github/shautvast/reflective/array/base/ShortArraySetter.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/github/shautvast/reflective/java/Java.java b/src/main/java/com/github/shautvast/reflective/java/Java.java
index b6235dd..1cda97e 100644
--- a/src/main/java/com/github/shautvast/reflective/java/Java.java
+++ b/src/main/java/com/github/shautvast/reflective/java/Java.java
@@ -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":
diff --git a/src/test/java/com/github/shautvast/reflective/array/ArrayFactoryTest.java b/src/test/java/com/github/shautvast/reflective/array/ArrayFactoryTest.java
new file mode 100644
index 0000000..bc81efb
--- /dev/null
+++ b/src/test/java/com/github/shautvast/reflective/array/ArrayFactoryTest.java
@@ -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));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/github/shautvast/reflective/array/ArraysTest.java b/src/test/java/com/github/shautvast/reflective/array/ArraysTest.java
deleted file mode 100644
index 0d730e1..0000000
--- a/src/test/java/com/github/shautvast/reflective/array/ArraysTest.java
+++ /dev/null
@@ -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);
- }
-}
\ No newline at end of file