views:

89

answers:

4

Hi,

I've been attempting to invoke a private method whose argument is a parameter and I can't quite seem to get it right.

Here's kind of how the code looks so far:

public class TestClass {
   public TestClass(){
   }

   private void simpleMethod( Map<String, Integer> testMap) {
      //code logic
   }
}

Then I attempt to use this to invoke the private method:

//instance I would like to invoke simpleMethod on
TestClass testClassObject = new TestClass();

//Hashmap
Map <String, Integer> testMap = new HashMap <String, Integer>();

//method I want to invoke
Method simpleMethod = TestClass.class.getDeclaredMethod("simpleMethod", Map.class);
simpleMethod.setAccessible(true);

simpleMethod.invoke(testClassObject, testMap); //Throws an IllegalArgumentException 

As you can see, it throws an IllegalArgumentException. I've attempted to cast the hashmap back to a map, but that didn't work.

What am I doing wrong?

+3  A: 

I just tested it, and your code works 100% fine here, when I instantiate your TestClass object like:

TestClass testClassObject = new TestClass();

Maybe you're using different imports (e.g. a different Map than java.util.Map)?

Chris Lercher
That's bizarre. Here's the error:object is not an instance of declaring classjava.lang.IllegalArgumentException: object is not an instance of declaring classWhat version of Java are you using chris_l?I'm using jdk1.6.0_16.
Stephanie
@Stephanie: This isn't going to depend on the JRE version, it's pretty fundamental.
skaffman
Tested too and runs like a charm (if I pass an object with the correct type to testClassObject ;-) )
Andreas_D
perhaps its a build/path issue? You run out of one jar (without the method), and build into another?
Justin
@Stephanie: I'm using 1.6.0_20. Have you tried emptying your implementation of simpleMethod, to narrow down the problem?
Chris Lercher
@chris_l: You know, I hadn't thought of that, but when I comment out the code in simpleMethod, it seems to throw the same exception :-(
Stephanie
@chris_l: You're right, when I run the code as a regular junit test class everything works as expected. I guess there's something else going on here. Thanks though, at least I know I'm not completely going insane for not writing the code the expected way.
Stephanie
@Stephanie: Have you tried copying stacker's code 1:1 (including all import statements)? Does that work for you?
Chris Lercher
@Stephanie: It works as a JUnit test? Are you maybe using some AOP framework (e.g. AspectJ) when running your code normally?
Chris Lercher
@chris_l: I actually copied and pasted my code on a clean project with junit and it worked as expected. My environment setup consists of running cactus junit tests against a glassfish server where the object I'm trying to invoke simpleMethod against is a remote object following the local/remote ejb interface.
Stephanie
+1 I _hate_ when this happens! :-)
trashgod
A: 

Method.invoke() takes two arguments. The first is the object to invoke the method upon. The second is an array of Objects, each representing a parameter. You need to change your invoke() call to:

simpleMethod.invoke(testClassObject, new Object[]{testMap});
VeeArr
Not necessary, when using Java 5 or later. The signature is: public Object invoke(Object obj, Object... args)
Chris Lercher
No, `Method.invoke()` takes a vararg list, not an array.
skaffman
not necesary since 5.0
leonbloy
Woops, seems my reflection knowledge is behind the times.
VeeArr
+1  A: 

Everything works just as expected and prints "simpleMethod invoked".

TestClass.java

import java.util.Map;

public class TestClass {
    public TestClass() {
    }
    private void simpleMethod(Map<String, Integer> testMap) {
        System.err.println("simpleMethod invoked");
    }
}

Caller.java

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Caller {
    public static void main(String[] args) throws IllegalArgumentException,
            IllegalAccessException, InvocationTargetException,
            SecurityException, NoSuchMethodException {
        // Hashmap
        Map<String, Integer> testMap = new HashMap<String, Integer>();

        // method I want to invoke
        Method simpleMethod = TestClass.class.getDeclaredMethod("simpleMethod",
                Map.class);
        simpleMethod.setAccessible(true);

        TestClass testClassObject = new TestClass();
        simpleMethod.invoke(testClassObject, testMap);
    }
}
stacker
Is this supposed to be in some way different that what the OP is already doing?
VeeArr
Repeating the question isn't really an answer....
skaffman
@skaffman, I couldn't find an issue so I tried to run it myself to find the problem, first in one classfile then in two but it just worked, would you please explain what I did wrong?
stacker
@stacker: Confirming a normative result, cited by @chris_l and noted by @John D, seems helpful, at least in retrospect. :-)
trashgod
+1  A: 

The code as posted works fine for me. Tweaking the code a little, I get an IllegalArgumentException when testMap is null. "wrong number of arguments".

John D