After adding a good answer, here's an awful answer, just for the heck of it. What bothers me about the Apache Commons ArrayUtils class is that there are 8 versions of the same method, just for different input types. I found a generic way to convert any primitive array into its wrapper equivalent (hence reducing the 8 different versions to one). This is the code:
@SuppressWarnings("unchecked")
public static <T> T[] toWrapperArray(final Object primitiveArray){
if(primitiveArray==null)
throw new NullPointerException("Null values are not supported");
final Class<?> cls = primitiveArray.getClass();
if(!cls.isArray()||!cls.getComponentType().isPrimitive())
throw new IllegalArgumentException(
"Only primitive arrays are supported");
final int length = Array.getLength(primitiveArray);
if(length==0)
throw new IllegalArgumentException(
"Only non-empty primitive arrays are supported");
T[] arr=null;
for (int i = 0; i < length; i++) {
final Object wrapped = Array.get(primitiveArray, i);
if(arr==null){
arr=(T[]) Array.newInstance(wrapped.getClass(), length);
}
arr[i]=(T) wrapped;
}
return arr;
}
As you can see, there's quite a lot wrong with that method:
- There's no compile-time safety:
- The method parameter can be anything and only the method itself will validate runtime parameters, rigorously rejecting null values, empty arrays, non-arrays and non-primitive arrays
- The return type can be assigned to any Object array type, which will fail with a ClassCastException if you choose the wrong type.
- Reflection was needed
- There is no way to support empty arrays without keeping some sort of lookup table between primitive and wrapper classes.
Anyway, here are two test methods. The first test the proper workings:
@Test
public void testWrappers() throws Exception {
final Integer[] wrappedIntegers = toWrapperArray(
new int[]{1,2,3});
assertArrayEquals(new Integer[]{1,2,3},wrappedIntegers);
final Long[] wrappedLongs = toWrapperArray(
new long[]{1l,2l,3l});
assertArrayEquals(new Long[]{1l,2l,3l},wrappedLongs);
final Boolean[] wrappedBooleans = toWrapperArray(
new boolean[]{true,false,false,true});
assertArrayEquals(new Boolean[]{true,false,false,true},wrappedBooleans);
}
The second tests the expected failures:
@Test
public void testWrapperFailures(){
try {
final Object[] wrapped = toWrapperArray(null);
fail("False positive with null value");
} catch (final Exception e) {}
try {
final Object[] wrapped = toWrapperArray(
"Elvis has left the building");
fail("False positive with non-Array object");
} catch (final Exception e) {}
try {
final Object[] wrapped = toWrapperArray(
new String[]{"Elvis", "has", "left", "the", "building"});
fail("False positive with non-primitive Array");
} catch (final Exception e) {}
try {
final Long[] wrapped = toWrapperArray(new int[]{1,2,3});
fail("False positive where ClassCastException should occur");
} catch (final Exception e) {}
}
Of course it's not possible to create such a method the other way around without keeping a lookup table, or is there?