Class:isAssignableFrom doesn't autobox primitives.

Object[] a = new Object[] {1.0f};
System.out.println(float.class.isAssignableFrom(a[0].getClass())); //returns false
System.out.println(Float.class.isAssignableFrom(a[0].getClass())); //returns true

Is there an elegant solution to this? I’m using this in tandem with Method:invoke, and the hackish solution right now is to change the parameters in the called function to their non-primitive counterparts, but that’s not really acceptable in the long run…

Just fill a Map<Class, Class> with primitive classes TO box classes

map.put(int.class, Integer.class);
map.put(float.class, Float.class);

Class<?> pass = …;
Class<?> box = map.get(pass);
if(box != null)
pass = box;

This way you replace your primitive types and keep all others.

It’s also probably much faster to just iterate over an array…


Class[] from = new Class[]{byte.class,short.class,......}
Class[] to = new Class[]{Byte.class,Short.class,......}


for(int i=0; i<9; i++)
   if(c == from[i])
       return to[i];
return c;

Perhaps i’m missing something but… is this Object array ‘a’ being used as the ‘args’ parameter to your call to Method:invoke(…)?

If so, the implementation automatically unwraps the Object types to their primitive counterparts, so you won’t have to do a thing?

Well, it unwraps the Object types to their primitive counterparts, but according to Sun’s reflection article, isAssignableFrom returns false if either class involved is a primitive. They don’t hint at any workaround though.

This got me curious as to how exactly Method:invoke(…) performs the automatic unwrapping of the ‘args’ parameters to their primitive types - whether they do what Riven suggested, or something more ‘magic’.

I wish now that I hadn’t looked, as it was:
a) a waste of time
b) shocking.

Apparently Method:invoke(…) falls through to the MethodAccessor interface; a concrete implementation of which is obtained from a MethodAccessorGenerator.
The MethodAccessorGenerator.generate(…) is the shocking part - it contains code to generate (at runtime) the bytecode representation of a class file (a subclass of ‘MagicAccessorImpl’ that implements the MethodAccessor interface.), that it subsequently defines, instanciates & returns.

Ergo there is no source code to read, or class file in the rt.jar to decompile, to see exactly how Method:invoke(…) does it’s magic :persecutioncomplex:

I suppose if you were realy interested you could try to hack the jre to store the runtime generated class definition somewhere… but I’ve a feeling the reason they don’t create the class file definition until runtime, is because this stuff is so low level it probably has to account for the code mangling that jit & hotspot are doing.

Darn…

I think your found the core of the overhead of reflection.

Are they caching the result for the Class[] that can be derived from an Object[] or are they simply generating bytecode for every invoke?

(Sorry, I’m too lazy to investigate, and you probably know it already)

The MethodAccessor is generated only once (the first time the method is invoked) for a Method, so no that won’t be the reason reflection is slow. (so long as you keep hold of the the Method instance for whatever it is you are invoking)

Sounds like its working as expected.

Your not passing a primitive at all nor a literal just a simple Class object which possibly belongs to a primitive.

Primitive and wrapper classes themselves get auto-boxed not their Runtime class objects.

Object[] a = new Object[] {1.0f};

auto-boxing already happens here the float is auto-boxed in a Float and then is put in the array.

Moreover even if the voodoo-magic your expecting was there, getClass() can’t be called on a float.

Also I thought auto-boxing was only there as syntax sugar not for weird constructs.