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