views:

3183

answers:

4

The idea is to define a base class that can invoke methods defined in derrived classes, but at creation time I want to ensure, that such methods are defined exactly according to the requirements, which is that the methods take only one argument, a HashMap<String String>.

So far I was able with the following code to check that the method contains only one parameter and that it is of Class HashMap, but how can I check that the generic definition is <String, String> ?

public boolean isMethodParameterValid(final Method method) {
  final Class<?>[] parameters = method.getParameterTypes();
  return ((parameters.length == 1) && parameters[0].isAssignableFrom(HashMap.class));
}
+7  A: 

You can't. Java generic types are "erased" by the compiler, i.e. HashMap<String, String> becomes just HashMap at run-time. See this question.

Dave Ray
+1  A: 

I dont really understand the goal of what you are trying to do. I have a feeling that it should be possible to check that at compile time by carefully designing your class hierarchy. But without more details on the problem you are trying to solve, I cant help you.

Guillaume
A: 

As noted, at runtime you cannot look at the generic portion of a type.

Is there a reason you can just define an abstract method as in the Template Pattern?

Then the checking will be done statically.

protected abstract void process(HashMap<String, String>);

(also is there a reason to require HashMap over just Map?)

Kathy Van Stone
+3  A: 

Indeed, there is type erasure but it is not applied to variables/fields - only to definitions of classes where the type params are erased and replaced with their upper bounds.

This means that what you are asking can be achieved. Here's how you can inspect the generic params of the first parameter of a method:

class Z
{
  public void f(List<String> lst) { }
}

...

Method m = Z.class.getMethod("f", List.class);
Type t = m.getGenericParameterTypes()[0];
if(t instanceof ParameterizedType) {
  ParameterizedType pt = (ParameterizedType) t;
  System.out.println("Generic params of first argument: " + Arrays.toString(pt.getActualTypeArguments()));
}
Itay