Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java reflection where a method parameter is an interface

First off let me say I am maintaining someone else's poorly designed code so I am limited in how much I can change it.

Now what is happening is that they have created a series of methods that are invoked by reflection. One of those methods takes a Map as one of its arguments. At runtime this Map is implemented with a Hashtable.

Here's the problem - I get a NoSuchMethodException because it is looking for a method with Hashtable as an argument even though a Hashtable implements the Map interface. What is confusing me is that if I don't use reflection (a major design change in this case) and passed a Hashtable it would invoke the method with the Map parameter - so why doesn't it work the same way when I use reflection?

Given that I pretty much have to stick with reflection is there any way to get the method with the Map argument to get invoked when I pass it a class that implements that interface?

If you want I can mock some code up to demonstrate...

like image 524
BigMac66 Avatar asked Aug 24 '10 16:08

BigMac66


People also ask

What is method parameter reflection in Java?

Overview. Method Parameter Reflection support was added in Java 8. Simply put, it provides support for getting the names of parameters at runtime. In this quick tutorial, we'll take a look at how to access parameter names for constructors and methods at runtime – using reflection.

Can I obtain method parameter name using Java reflection?

You can obtain the names of the formal parameters of any method or constructor with the method java. lang. reflect.

Can we pass interface as a parameter to a method in Java?

Yes, you can pass Interface as a parameter in the function.

How do I stop reflection in Java?

The enabler of the technique used to avoid the very slow reflection is the invokedynamic bytecode instruction. Briefly, invokedynamic (or “indy”) was the greatest thing introduced in Java 7 in order to pave the way for implementing dynamic languages on top of the JVM through dynamic method invocation.


2 Answers

If you are using getMethod(String name, Class[] parameterTypes) from java.lang.Class, you need to specify parameter types as expressed in the method signature of the interface (static type), not the type of the object at run-time (dynamic type).

So, for methodXyz(Map map), instead of:

Method m = cl.getMethod("methodXyz", new Class[]{argument.getClass()});

do this:

Method m = cl.getMethod("methodXyz", new Class[]{Map.class});
like image 85
gawi Avatar answered Oct 05 '22 23:10

gawi


I had a similar problem. I see 2 solutions:

solution 1: you can develop a more complicated search method.

Example of an algorithm you could use :

You search with the parameter type. If the search fails (Exception), but one of the parameters has a super type (or implements an interface), you search the same method name, but with this superclass (or interface). You throw the exception only if no method is found after this search algorithm.

Note : if your methods have several parameters, be sure to verify with each possible combination of supertypes/interfaces. It can result in a quite complex search algorithm...

solution 2: another method, much easier, is to precise the types separately from the parameters. This method more verbose can be necessary if you want to use null parameters.

So, "invokeMethod(String methodName, Object[] paramters)" becomes "invokeMethod(String methodName, Class[] methodParamTypes, Object[] parameters)".

like image 44
Benoit Courtine Avatar answered Oct 06 '22 01:10

Benoit Courtine