Two Side Notes About Arrays and Reflection

Two Side Notes About Arrays and Reflection
Yesterday I read a post by Jakob Jenkov about using reflection to work with Java arrays. It is a nice post but I have two comments about it:


1. The Array Class

At the end of his post Jakob wrote that he couldn't find a way to obtain the class of an array using the class.forName() method. Here is the solution for that: The JVM has an internal representation for each type. To represent native types the JVM uses one character codes (you can see it in section 4.3.2 on the JVM specifications – second edition):

Type
JVM Representation
byte
B
char
C
double
D
float
F
int
I
long
J
short
S
boolean
Z

Objects (none native types) are represented as references in the following form L; (the semicolon is a part of the representation). And array dimensions are represented as a single [ (square bracket) on the left side of the type representation. Some examples:

Internal Representation
Java Type
[Ljava.lang.Integer;
Integer[]
[[B
byte[][]
[[Ljava.lang.Byte;
Byte[][]

So to obtain the class of the int[] using Class.forName() I can use the following syntax:

Class.forName("[I");

However, when trying to instantiate an int[] out of it (in the original post the author didn't write why did he need the class of the array) I will get into a problem:


Class c = Class.forName("[I");
Object arr = Array.newInstance(c, 3);

The type of arr will be int[][] and not int[]. So maybe I should try:


Class c = Class.forName("[I");
Object arr = c.newInstance();

The newInstance() method will throw an InstantiationException. The naive solution would be just to remove the "[" from the Class.forName() method and then to create the array using the Array class:


Class clazz = Class.forName("I");
Object arr = Array.newInstance(clazz, 5);

But this one will throw a ClassNotFoundException - we can obtain a reference to the class of any primitive type array using Class.forName() but we can't get a reference to the primitive type's class itself. The only way I know to do it is to use the wrapper type's TYPE member. There is a method in the Class class that gets the class of a primitive type (getPrimitiveClass()) but this is not a public method. Each wrapper type has a public member named TYPE that holds a reference to the wrapped class. So finally - how to create an array of native types using reflection:



    public static Object createNativeArray(String typeName, int...dim) throws ClassNotFoundException  {
        Class clazz = null;
        if ("int".equals(typeName)) {
            clazz = Integer.TYPE;
        } else if ("boolean".equals(typeName)) {
            clazz = Boolean.TYPE;
        } else if ("double".equals(typeName)) {
            clazz = Double.class;
            //All other native types: short, long, float ......
        }else {
            throw new ClassNotFoundException(typeName);
        }
   
        return Array.newInstance(clazz, dim);
    }


2. Getting the Component Type

One thing I think was missing in the post is how to get the type of the array elements using reflection. This can be done using the getComponentType() method:


Boolean[] b = new Boolean[5];
Class theTypeOfTheElements = b.getClass().getComponentType();
System.out.println(theTypeOfTheElements.getName());


That’s it, just two side notes about arrays and reflection. 



Please notice: I had recover this blog post from my old blog at http://www.jroller.com/eyallupu since jroller.com is no longer available.  As such the styling might be a bit wobbly ... If something seems 'too broken' please contact me and I'll adjust 

Comments

Popular posts from this blog

New in Spring MVC 3.1: CSRF Protection using RequestDataValueProcessor

Hibernate Exception - Simultaneously Fetch Multiple Bags

Hibernate/JPA Identity Generators