Working with Arrays
Arrays are implemented in the Java virtual machine. The only methods on arrays are those inherited from Object. The length of an array is not part of its type; arrays have a length field which is accessible via Array.getLength(Object)
.
Reflection provides methods for accessing array types and array component types, creating new arrays, and retrieving and setting array component values.
Identifying Array Types
Array types may be identified by invoking Class.isArray()
.
You can get the exact type of the internal array on a String
object with the following code.
Class<?> c = String.class;
Field field = c.getDeclaredField("value");
Class<?> fieldType = field.getType();
boolean isArray = fieldType.isArray();
System.out.println("isArray = " + isArray);
Class<?> elementType = fieldType.getComponentType();
System.out.println("elementType = " + elementType);
Running the previous code prints the following.
isArray = true
elementType = byte
Creating New Arrays
Just as in non-reflective code, reflection supports the ability to dynamically create arrays of arbitrary type and dimensions via java.lang.reflect.Array.newInstance()
.
The Array
class contains a collection of static method to get reflective information on arrays, as well as to set and read the elements on any array.
Let us consider the following code.
int length = 10;
Object o = Array.newInstance(int.class, 10);
boolean isArray = o.getClass().isArray();
System.out.println("isArray = " + isArray);
Class<?> componentType = o.getClass().getComponentType();
System.out.println("componentType = " + componentType);
int reflectiveLength = Array.getLength(o);
System.out.println("reflectiveLength = " + reflectiveLength);
for (int i = 0; i < reflectiveLength; i++) {
Array.set(o, i, 2*i);
}
System.out.println(Arrays.toString((int[])o));
Let us comment this code line by line.
Array.newInstance(int.class, 10)
: creates a new instance of an array of 10int
.o.getClass().isArray()
: check if the corresponding class is an array class.o.getClass().getComponentType()
: returns the type of the components of this array. In this case, it isint
.Array.getLength(o)
: returns the length of this array.Array.set(o, i, 2*i)
: reflectively set the i th element of the arrayo
to the value2*i
. You can also reflectively read the i th element of the arrayo
with theArray.get(o, i)
method call.
Note that the Array
class has methods to set primitive values without boxing or unboxing. For example, you can use Array.setDouble()
and Array.getDouble()
to set and get the elements of an array of double
.
There are two elements to consider when using these methods.
- Calling a
setFloat()
method with aFloat
object instead of afloat
primitive type will throw anIllegalArgumentException
. - Calling
Arrays.setInt()
and passing an array of longs is OK, as there is no loss of precision when converting anint
to along
. The contrary is illegal. You cannot callArrays.setLong()
, passing an array of ints, as it would lead to a loss of precision due to the narrowing of yourlong
.
Running the previous code prints the following.
isArray = true
componentType = int
reflectiveLength = 10
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Note that trying to read or write elements at an index greater than the length of this array will throw an ArrayIndexOutOfBoundsException
.
Last update: July 25, 2024