Invoking ArrayList.get() impossible with reflection ?

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

Sébastien de Mapias

Hi,

I'm asking my question of 2 days ago another way today.
I have a class that contains the code:

~ Class<?> coll = Class.forName(ref.getClass().getName());
~ Method[] methods = coll.getDeclaredMethods();
~
~ for (Method method : methods)
~ {
~ method.setAccessible(true);
~
~ try {
~ Object o = method.invoke(ref, (Object[])null);
~ System.out.println("OK METHOD NAME "+method.getName());
~ } catch (java.lang.IllegalArgumentException iae) {
~ System.out.println("FAILS FOR "+method.getName());
~ }
~ }

My var 'ref' is a reference to a java.util.ArrayList<Something>.
I've tried the code above with
~ Object o = method.invoke(ref, (Object[])null);
and the 2nd argument of 'invoke' left to null:
~ Object o = method.invoke(ref);

I get the following in both cases (the *same* output):
~ OK METHOD NAME trimToSize
~ FAILS FOR ensureCapacity
~ OK METHOD NAME size
~ OK METHOD NAME isEmpty
~ FAILS FOR contains
~ FAILS FOR indexOf
~ FAILS FOR lastIndexOf
~ OK METHOD NAME clone
~ OK METHOD NAME toArray
~ FAILS FOR toArray
~ FAILS FOR get
~ FAILS FOR set
~ FAILS FOR add
~ FAILS FOR add
~ FAILS FOR remove
~ FAILS FOR remove
~ FAILS FOR fastRemove
~ OK METHOD NAME clear
~ FAILS FOR addAll
~ FAILS FOR addAll
~ FAILS FOR removeRange
~ FAILS FOR RangeCheck
~ FAILS FOR writeObject
~ FAILS FOR readObject

So the invocation of most methods of the ArrayList implementation
fails.
IMPORTANT: it fails with the error "wrong number of arguments".
How come ?? 'invoke()' can be called with one, or 2 args right ?
What am I missing here ?

Anybody has any idea why please ?

Please !
Thanks a lot...
Sébastien
 
J

Joshua Cranmer

Sébastien de Mapias said:
I get the following in both cases (the *same* output):
~ OK METHOD NAME trimToSize
~ FAILS FOR ensureCapacity
~ OK METHOD NAME size
~ OK METHOD NAME isEmpty
~ FAILS FOR contains
~ FAILS FOR indexOf
~ FAILS FOR lastIndexOf
~ OK METHOD NAME clone
~ OK METHOD NAME toArray
~ FAILS FOR toArray
~ FAILS FOR get
~ FAILS FOR set
~ FAILS FOR add
~ FAILS FOR add
~ FAILS FOR remove
~ FAILS FOR remove
~ FAILS FOR fastRemove
~ OK METHOD NAME clear
~ FAILS FOR addAll
~ FAILS FOR addAll
~ FAILS FOR removeRange
~ FAILS FOR RangeCheck
~ FAILS FOR writeObject
~ FAILS FOR readObject

Notice anything about the methods that succeed and the ones that fail?
Let's look at the Javadocs for select ones:

void trimToSize();
[ ensureCapacity isn't in there... it's a private method, so you
violated an access constraint. ]
int size()
boolean isEmpty()
boolean contains(Object o)
int indexOf(Object o)
int lastIndexOf(o)
....

Hey, there's a pattern! This fails for
a. Non publicly accessible methods and
b. Methods with arguments.

What you want to do is you want to pass the parameters into invoke, e.g.,

invoke(ref, 0) for a 1-arg method, or
invoke(ref, 5, null) for a 2-arg method, etc.
 
T

Tom Anderson

So the invocation of most methods of the ArrayList implementation
fails.
IMPORTANT: it fails with the error "wrong number of arguments".
How come ?? 'invoke()' can be called with one, or 2 args right ?
What am I missing here ?

It means you've passed the wrong number of arguments for the method you're
trying to invoke reflectively, not the invoke method itself.

List.get takes one argument, an integer, so when you call it with no
arguments, it doesn't work. If you pass in an integer, it will work.

Try:

int index = 0 ;
Object o = method.invoke(ref, index);

That will work.

It will fail for most of the other methods, since they have different
argument lists.

There's no straightforward way to invoke an arbitrary method so that it
will work. But why would you want to do that anyway?

tom
 
L

Lothar Kimmeringer

Tom said:
There's no straightforward way to invoke an arbitrary method so that it
will work. But why would you want to do that anyway?

Maybe he was using ArrayLIst just as example to avoid the
posting of the source of the class where he actually had
the problem.

And calling methods by Reflection is nothing special.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
L

Lew

Lothar said:
And calling methods by Reflection is nothing special.

True, as long as the loss of compile-time type safety, sharp increase
in code complexity and the pronounced additional risk of bugs are
nothing special. Not to mention the utter obfuscation of the purpose
of the code.
 
M

Mike Schilling

Lew said:
True, as long as the loss of compile-time type safety, sharp increase
in code complexity and the pronounced additional risk of bugs are
nothing special. Not to mention the utter obfuscation of the purpose
of the code.

And it's significantly slower. But besides that, no big deal.
 
L

Lothar Kimmeringer

Mike said:
Lew wrote:

(Lew canceled his post to post something else into another
newsgroup where the original post never appeared, so I have
to answer him via your post)

"nothing special" in the meaning of "there are situations when
you need reflection and there is no reason to not use it in
that case":

Some reasons are:

- Serialization-mechanisms in general (e.g. XML-marshalling,
Axis creating a WebService-Request out of a POJO), etc.
- Calling methods of classes that were loaded by a different
class-loader. Even if you have the class in your own class-
path you will get a ClassCastException when you try to cast
it to that specific class. So you have to work with object
using reflection
- Methods-calls configured by a config-file

Using reflrection is comparable to using Object or Exception
as parameter/checked exceptoin rather than a more specialized
form. You lose compile-time-checks and all the things but there
are situations where you have to do exactly that.
And it's significantly slower. But besides that, no big deal.

True, but the above situations can't be solved differently, so
you have to live with it. And compared to the time, the called
method needs for execution the overhead of reflection doesn't
fall into much account. To show the numbers. 10^7 calls
using reflection take 1.5 seconds on my machine. 10^8 direct
calls take 0.3 seconds. So we are talking of a factor of about
50. Sounds big but looking at the absolute numbers shows that
the difference between a call using reflection and a direct
call is 0.15 milliseconds. If the called method needs significant
more time to execute you can simply ignore that.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
J

Joshua Cranmer

Lothar said:
(Lew canceled his post to post something else into another
newsgroup where the original post never appeared, so I have
to answer him via your post)

Lew didn't cancel his post, it's the NewsMaestro troll trying to defraud
him.
 
L

Lothar Kimmeringer

The post Mike is aswering to never appeared here, but there
is a post in comp.lang.java.help:

| Newsgroups: comp.lang.java.help
| Subject: Re: Invoking ArrayList.get() impossible with reflection ?
| Supersedes: <a1ba360c-7589-4d8f-bd38-bfe9b00487e0@k30g2000hse.googlegroups.com>
| Date: Fri, 19 Sep 2008 11:23:46 GMT
| Message-ID: said:
Nor is it gone from this newsgroup.

Not here. If you use Google Groups. Canceled articles are not
removed from the list immediately.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
L

Lothar Kimmeringer

Lew said:
I guess your version of "here" differs from mine.

Of course, that's Usenet.
Apparently "canceled"
(actually, "Superseded" is the operative term) articles are actually never
removed from "here".

And that's the reason why you see your post. The newsserver of Puretec
is acting different, so "here" your original post can not be seen
anymore.
If they are removed from Google Groups, well, that's just more evidence that
one shouldn't use Google Groups. Use a real news service.

Are you talking with me? I'm not using Google Groups as you can easily
find out by looking into the headers.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
T

Tom McGlynn

True, but the above situations can't be solved differently, so
you have to live with it. And compared to the time, the called
method needs for execution the overhead of reflection doesn't
fall into much account. To show the numbers. 10^7 calls
using reflection take 1.5 seconds on my machine. 10^8 direct
calls take 0.3 seconds. So we are talking of a factor of about
50. Sounds big but looking at the absolute numbers shows that
the difference between a call using reflection and a direct
call is 0.15 milliseconds. If the called method needs significant
more time to execute you can simply ignore that.

Hi Lothar,

Did you drop a factor of 1000 somewhere? Your timing numbers would
suggest
it takes 150 nanoseconds for a reflective call and 3 nanoseconds for a
non-reflective call -- not microseconds. This just emphasizes your
point that if
the routine takes any significant time to complete, the reflection
overhead
can be amortized without significant slowing of the program. I'd
always
wondered what the cost of a reflective call was and your test suggests
it's a few hundred machine cycles assuming you did this on a ~GHz
machine.

Regards,
Tom McGlynn
 
S

Sébastien de Mapias

Some reasons are:
 - Serialization-mechanisms in general (e.g. XML-marshalling,
   Axis creating a WebService-Request out of a POJO), etc.

YES Lothar, gut gemerkt !: I need to use reflection
because I'm dealing with an arborescence of objects
coming from an unmarshalling process (want to re-create
the whole tree-structure and resolve references before
storing the whole stuff in a database -then Hibernate
takes the relay and does this job-).

I'm *sorry* I posted this question completely confused
with iterator.next() (which takes NO argument), because
I was facing several issues and I mixed things up a bit...

Thanks for your answers.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top