damon
damon

Reputation: 8477

java reflection to invoke a method that takes a Comparable[] argument

I have a class with a static method which takes a Comparable[] as argument.

I need to find and invoke the method .I tried the following with java reflection

class X{

    public static void sort(Comparable[] a){
        System.out.println("sorting");
    }
    public static void read(String name){
        System.out.println("name="+name);
    }
}

...
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {
        String[] a= new String[]{"E","X","A","M","P","L","E"};
        Class xc = Class.forName("my.javacode.X");

        Method m2 = xc.getMethod("read", java.lang.String.class);
        m2.invoke(null, "jon");

        Method m1 = xc.getMethod("sort", Comparable[].class);
        System.out.println(m1);
        m1.invoke(null, a);

    }
..

this produced an exception

name=jon
public static void my.javacode.X.sort(java.lang.Comparable[])
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at my.javacode.Misc.main(Misc.java:36)

Any idea how to correct this? The Comparable[].class argument in getMethod() returns the correct method object..However the invoke fails when the String[] is passed..I am trying to implement sort() as generic method sothat it can work for arrays of Wrapper types..(like Integer[],Double[],String[] etc)

Any advice/correction appreciated.

Upvotes: 3

Views: 1202

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500525

When you call Method.invoke with this signature:

public Object invoke(Object obj, Object... args)

... the varargs parameter is only used as a varargs parameter when it would fail otherwise.

So this call:

m2.invoke(null, "jon");

is equivalent to:

m2.invoke(null, new Object[] {"jon"});

But String[] is implicitly convertible to Object[], so this call:

m1.invoke(null, a);

is not expanded to wrap a in an Object[]. It's trying to call the method as if it's got 7 string parameters rather than one array parameter.

Two options:

  • Declare a as type Object rather than String[], which will then make the compiler perform the wrapping for you.
  • Explicitly wrap it in an array:

    m1.invoke(null, new Object[] { a });
    

Either should be fine.

Upvotes: 6

Related Questions