Download the JDK
Search the Tutorials
Hide the TOC
Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Arrays
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
Troubleshooting

> The following examples show typical errors which may occur when operating on arrays.

> ### IllegalArgumentException due to Inconvertible Types

> The ``ArrayTroubleAgain`` example will generate an `IllegalArgumentException`. `Array.setInt()` is invoked to set a component that is of the reference type `Integer` with a value of primitive type `int`. In the non-reflection equivalent `ary[0] = 1`, the compiler would convert (or box) the value `1` to a reference type as `new Integer(1)` so that its type checking will accept the statement. When using reflection, type checking only occurs at runtime so there is no opportunity to box the value.

> >     import java.lang.reflect.Array;
> >     import static java.lang.System.err;

> >     public class ArrayTroubleAgain {
> >         public static void main(String... args) {
> >     	Integer[] ary = new Integer[2];
> >     	try {
> >     	    Array.setInt(ary, 0, 1);  // IllegalArgumentException

> >             // production code should handle these exceptions more gracefully
> >     	} catch (IllegalArgumentException x) {
> >     	    err.format("Unable to box%n");
> >     	} catch (ArrayIndexOutOfBoundsException x) {
> >     	    x.printStackTrace();
> >     	}
> >         }
> >     }

> >     $ java ArrayTroubleAgain
> >     Unable to box

> To eliminate this exception, the problematic line should be replaced by the following invocation of `Array.set(Object array, int index, Object value)`:

> >     Array.set(ary, 0, new Integer(1));

> > Tip: When using reflection to set or get an array component, the compiler does not have an opportunity to perform boxing. It can only convert types that are related as described by the specification for `Class.isAssignableFrom()`. The example is expected to fail because `isAssignableFrom()` will return `false` in this test which can be used programmatically to verify whether a particular conversion is possible:

> > >     Integer.class.isAssignableFrom(int.class) == false

> > Similarly, automatic conversion from primitive to reference type is also impossible in reflection.

> > >     int.class.isAssignableFrom(Integer.class) == false

> ### ArrayIndexOutOfBoundsException for Empty Arrays

> The ``ArrayTrouble`` example illustrates an error which will occur if an attempt is made to access the elements of an array of zero length:

> >     import java.lang.reflect.Array;
> >     import static java.lang.System.out;

> >     public class ArrayTrouble {
> >         public static void main(String... args) {
> >             Object o = Array.newInstance(int.class, 0);
> >             int[] i = (int[])o;
> >             int[] j = new int[0];
> >             out.format("i.length = %d, j.length = %d, args.length = %d%n",
> >                        i.length, j.length, args.length);
> >             Array.getInt(o, 0);  // ArrayIndexOutOfBoundsException
> >         }
> >     }

> >     $ java ArrayTrouble
> >     i.length = 0, j.length = 0, args.length = 0
> >     Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
> >             at java.lang.reflect.Array.getInt(Native Method)
> >             at ArrayTrouble.main(ArrayTrouble.java:11)

> > Tip: It is possible to have arrays with no elements (empty arrays). There are only a few cases in common code where they are seen but they can occur in reflection inadvertently. Of course, it is not possible to set/get the values of an empty array because an `ArrayIndexOutOfBoundsException` will be thrown.

> ### IllegalArgumentException if Narrowing is Attempted

> The ``ArrayTroubleToo`` example contains code which fails because it attempts perform an operation which could potentially lose data:

> >     import java.lang.reflect.Array;
> >     import static java.lang.System.out;

> >     public class ArrayTroubleToo {
> >         public static void main(String... args) {
> >             Object o = new int[2];
> >             Array.setShort(o, 0, (short)2);  // widening, succeeds
> >             Array.setLong(o, 1, 2L);         // narrowing, fails
> >         }
> >     }

> >     $ java ArrayTroubleToo
> >     Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
> >             at java.lang.reflect.Array.setLong(Native Method)
> >             at ArrayTroubleToo.main(ArrayTroubleToo.java:9)

> > Tip: The `Array.set*()` and `Array.get*()` methods will perform automatic widening conversion but will throw an `IllegalArgumentException` if a narrowing conversion is attempted. For complete discussion of widening and narrowing conversions, see The Java Language Specification, Third Edition, sections 5.1.2 and 5.1.3 respectively.

Previous page: Getting and Setting Arrays and Their Components
Next page: Enumerated Types