Thursday, February 11, 2010

Beware when reflecting on Java arrays

From JLS 10.7 (Array Members):
The members of an array type are all of the following:
  • The public final field length, which contains the number of components of the array (length may be positive or zero).
  • The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
  • All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Unfortunately, life isn't all peaches and cream...
import java.util.*;

public class ArrayReflection {
   public static void main(String args[]) {
      int[] arr = { 1, 2, 3, };
      System.out.println(arr.length);
      System.out.println(Arrays.toString(arr.clone()));

      // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5047859
      try {
         arr.getClass().getField("length");
      } catch (Exception e) {
         e.printStackTrace();
      }

      // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4987375
      try {
         arr.getClass().getMethod("clone");
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}
If you run the above code, it produces the following output:
3
[1, 2, 3]
java.lang.NoSuchFieldException: length
   at java.lang.Class.getField(Unknown Source)
   at ArrayReflection.main(ArrayReflection.java:11)
java.lang.NoSuchMethodException: [I.clone()
   at java.lang.Class.getMethod(Unknown Source)
   at ArrayReflection.main(ArrayReflection.java:18)
It would seem that the mirror does lie sometimes.
I will conclude by quoting Effective Java: "Prefer lists to arrays", and perhaps more importantly, "Prefer interfaces to reflection". Nonetheless, if you must reflect on arrays, see examples on how to use java.lang.reflect.Array from this technical article on Java reflection.

No comments:

Post a Comment