How would you invoke arrayList.get() through reflection in 1.4 ??

  • Thread starter Sébastien de Mapias
  • Start date
S

Sébastien de Mapias

Hi,

It seems to be pretty hard to invoke the List get(int) method through
reflection. I didn't manage to have my code working with my 1.4
compiler.
To sum up I do the following:

Method method;
method = [some more code...];
if (method.getReturnType().toString().equals("interface
java.util.List"))
{

// how many refs does our List contain ?
int n = sizeOfCollection(method.invoke(root, (Object[])null));

// let's get the actual list
Object list = method.invoke(root, (Object[])null);

// now trying to invoke its 'get()' for every element it
// contains:
Class listClass = Class.forName(list.getClass().getName());
Method m2 = listClass.getDeclaredMethod("get", ???); //<= what to
put here ?

for (int i=0; i<n; i++) {
Object o = m2.invoke(list, i); //<= doesn't compile
...
}
[...]
}

private int sizeOfCollection(Object obj)
{
return new StringTokenizer(obj.toString(), ",").countTokens();
}

In Java5 I managed to reach a point where I could traverse
all references contained in a List, and display them, but in 1.4,
no way: if someone every succeeded doing that, I'd be glad to
hear how you did it... Thanks a lot in advance !

Regards,
Seb
 
M

markspace

Sébastien de Mapias said:
Hi,

It seems to be pretty hard to invoke the List get(int) method through
reflection. I didn't manage to have my code working with my 1.4
compiler.

It isn't. Your code is pretty bad. I'll make some more comments about
that in a sec, you're making things way harder than need to be. First,
a direct answer to your question:

Method m = obj.getClass().getMethod( "get", Integer.TYPE );

Likely you have "Integer.class" or similar, you have to use the type for
a primitive, not the object Integer.

Ok, on to comments.

To sum up I do the following:

Method method;
method = [some more code...];
if (method.getReturnType().toString().equals("interface
java.util.List"))


That line above drives me nuts. Why do a string compare? Why not just
compare to the class itself?

> if (method.getReturnType() == List.class )


Not sure what the confusion is with that.

{

// how many refs does our List contain ?
int n = sizeOfCollection(method.invoke(root, (Object[])null));


That line is a terrible idea. More later.

// let's get the actual list
Object list = method.invoke(root, (Object[])null);


At this point you could just cast to a list, you know. This is the
biggest "wtf?" in your code for me.

List<?> list = (List) obj;
for( Object o : list ) {
System.out.println( o );
}

There's your "reflective" way to get all members of the list from an Object.

// now trying to invoke its 'get()' for every element it
// contains:
Class listClass = Class.forName(list.getClass().getName());
Method m2 = listClass.getDeclaredMethod("get", ???); //<= what to
put here ?

See above.
for (int i=0; i<n; i++) {
Object o = m2.invoke(list, i); //<= doesn't compile
...
}
Ditto.

[...]
}

private int sizeOfCollection(Object obj)
{
return new StringTokenizer(obj.toString(), ",").countTokens();
}

A close second place for "wtf?". Please. What if your string(s)
contain commas themselves? This can't work in the general case. Bad
bad code, bad idea. Just cast to a list and then call the normal
methods, like ".size()".



Here's my reflective example:

package oldlist;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;


public class Main {
public static void main(String[] args) throws NoSuchMethodException
{
Object x = Arrays.asList( "red", "fish", "blue", "fish" );
reflectList( x );
}

private static void reflectList( Object obj )
throws NoSuchMethodException
{
if( obj instanceof List ) {
List<?> list = (List) obj;
for( Object o : list ) {
System.out.println( o );
}
}
Method m = obj.getClass().getMethod( "get", Integer.TYPE );
System.out.println( m );
}
}
 
M

Mike Schilling

markspace said:
It isn't. Your code is pretty bad. I'll make some more comments
about that in a sec, you're making things way harder than need to
be.
First, a direct answer to your question:

Method m = obj.getClass().getMethod( "get", Integer.TYPE );

I was going to correct you, but checked first and saw that getMethod()
is now declared as varargs. Very handy.
 
M

markspace

Mike said:
I was going to correct you, but checked first and saw that getMethod()
is now declared as varargs. Very handy.


Ah ha.... I had set my compiler flags to -source 1.4 -target 1.4, but
apparently there's still a few sneaky things that don't get checked
directly. I didn't look at the 1.4 docs closely enough, I suppose.

Method m=obj.getClass().getMethod("get",new Class[]{Integer.TYPE});

Seems to work for me also, and I suspect will work on an older compiler
as well.
 
L

Lew

Mike said:
I was going to correct you, but checked first and saw that getMethod()
is now declared as varargs.  Very handy.

The varargs feature wasn't introduced until Java 5. Go ahead and
correct him.
 
M

MikisM

           List said:
           for( Object o : list ) {
              System.out.println( o );
           }
        }

I'm not 100% sure but weren't generics (<?> in this case) included in
1.5 version? The code should not compile with 1.4.
 
M

markspace

MikisM said:
I'm not 100% sure but weren't generics (<?> in this case) included in
1.5 version? The code should not compile with 1.4.


Yup, and that for:)) loop doesn't work either under 1.4. I put -source
1.4 on the compile line for javac, but it didn't work. Up further in
the same dialog there's a sources tab, with a drop down for the source
revision. Setting it there works. This is using Netbeans, under the
project Properties.

Thanks for provoking me into figuring this out.
 
D

Daniel Pitts

Sébastien de Mapias said:
Hi,

It seems to be pretty hard to invoke the List get(int) method through
reflection. I didn't manage to have my code working with my 1.4
compiler.
Why? Why not use ((List)obj).get(i);
That is *much* easier than using reflection.
To sum up I do the following:

Method method;
method = [some more code...];
if (method.getReturnType().toString().equals("interface
java.util.List"))
{

// how many refs does our List contain ?
int n = sizeOfCollection(method.invoke(root, (Object[])null));

// let's get the actual list
Object list = method.invoke(root, (Object[])null);

// now trying to invoke its 'get()' for every element it
// contains:
Class listClass = Class.forName(list.getClass().getName());
Method m2 = listClass.getDeclaredMethod("get", ???); //<= what to
put here ?

for (int i=0; i<n; i++) {
Object o = m2.invoke(list, i); //<= doesn't compile
...
}
[...]
}

private int sizeOfCollection(Object obj)
{
return new StringTokenizer(obj.toString(), ",").countTokens();
}

In Java5 I managed to reach a point where I could traverse
all references contained in a List, and display them, but in 1.4,
no way: if someone every succeeded doing that, I'd be glad to
hear how you did it... Thanks a lot in advance !

Regards,
Seb
 
L

Lew

markspace said:
Yup, and that for:)) loop doesn't work either under 1.4. I put -source
1.4 on the compile line for javac, but it didn't work. Up further in
the same dialog there's a sources tab, with a drop down for the source
revision. Setting it there works. This is using Netbeans, under the
project Properties.

Thanks for provoking me into figuring this out.

you probably also needed "-target 1.4" and perhaps even
"-bootclasspath $JDK14/rt.jar"
 
M

markspace

Lew said:
you probably also needed "-target 1.4" and perhaps even

I had that, it didn't seem to work either.

Under Properties -> Libraries, there's a "Java Platform" drop down menu.
I don't have Java 1.4 installed, so I can't check, but I'm going to
guess that switching that menu will enable NetBeans to use a different
JDK and also set the -target flag correctly.
 
J

John B. Matthews

markspace said:
I had that, it didn't seem to work either.

Under Properties -> Libraries, there's a "Java Platform" drop down menu.
I don't have Java 1.4 installed, so I can't check, but I'm going to
guess that switching that menu will enable NetBeans to use a different
JDK and also set the -target flag correctly.

I was similarly stymied for a time in NetBeans 6.5. On my machine, Java
1.5 is the default; I had to add 1.4.2 and 1.6 in the Tools -> Java
Platforms dialog. Even after making 1.6 available, I couldn't change
Properties -> Source/Binary Format to JDK 6 until I first set Properties
-> Libraries -> Java Platform to JDK 1.6.
 
R

Roedy Green

if (method.getReturnType().toString().equals("interface
java.util.List"))
if you know at compile time you are looking for a java.util.List
interface object, you don't need reflection or anything fancy. Just
do a Class.forName and cast to a (List) or use generics to cast it for
you. You can then use a List ref to access all the methods of List
in a straightforward way.

--
Roedy Green Canadian Mind Products
http://mindprod.com

Without deviation from the norm, progress is not possible.
~ Frank Zappa (born: 1940-12-21 died: 1993-12-04 at age: 52)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top