1

I'm sorry if this is a noob question. I have a method which takes a Class object with the generic type as a parameter. I am able to do the following:

Class cs = Map.class;

but when I pass this I get an "NoSuchMethodException" since the method is declared:

public void doSomething(Class<Map<Object, List<Object>>> theclass){
...     
}

I have tried to cast it like this:

Class cs = (Class<Map<Object, List<Object>>>)(Class<?>)Map.class;

but I still get the same exception.

Is there a way to do this?

I cannot post the full code here but I have reproduced the error: The application is actually using reflection. I can not post the original code here but I have reproduced the exception:

import java.lang.reflect.Method;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Class c = null;
        try {
            c = Class.forName("Second");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        String m = "doSomething";
        Method method = null;
        Class cs = Map.class;
        try{
            method = c.getMethod(m, cs);
        } catch (NoSuchMethodException e){
            e.printStackTrace();
        }
    }
}

class Second{
    public static void doSomething(Class<Map<Object, List<Object>>> theclass){
        System.out.println("HERE I AM!");   
    }   
}

The exception:

java.lang.NoSuchMethodException: Second.doSomething(java.util.Map)
    at java.lang.Class.throwNoSuchMethodException(Class.java:283)
    at java.lang.Class.getMethod(Class.java:825)
    at Main.main(Main.java:16)
Miretz
  • 154
  • 1
  • 12
  • 4
    You're trying to fight type erasure. – SLaks Sep 24 '12 at 12:04
  • check this out http://docs.oracle.com/javase/tutorial/java/generics/erasure.html – aviad Sep 24 '12 at 12:07
  • What statement is throwing the exception? – Vitaliy Sep 24 '12 at 12:08
  • Please show us the code that causes the exception to be thrown. Simply passing the wrong `Class` object as a method parameter is not going to cause it to happen. You must be doing something else. – Stephen C Sep 24 '12 at 12:09
  • 1
    Note that `public void doSomething(Class>> theclass)` is not a useful method signature, since it requires that `theClass` be *exactly* the class denoted `Map>`, so there is only one non-`null` value that could ever be passed to that method. Maybe you wanted to write `public void doSomething(Class extends Map>> theclass)` (which would also accept subclasses)? – ruakh Sep 24 '12 at 12:10
  • A `Class` represents a class or interface, such as a `Map`. To represent a parameterised type, you need something like `ParameterizedType`: http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/ParameterizedType.html (But your issue is you are using `Map.class` instead of `Class.class`, and some raw types and reflection.) – Tom Hawtin - tackline Sep 24 '12 at 13:56

2 Answers2

1

If you're doing such casting, I think you're fighting against the type system that's designed to help you. For starters,

Class cs = Map.class;

is a raw type (see here for more info). Have you tried instantiating a class of your required Map type, and passing the class of that to your function ?

e.g.

(new HashMap<Object, List<Object>>()).getClass();

Note: as ruakh as noted in the comments above, you'd have to pass an instance of the Map interface, and as such that method declaration above would prohibit this. Basically there's a fundamental API design issue here!

Community
  • 1
  • 1
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • But the method, as listed, wouldn't accept such an argument, due to invariance. (See my comment above.) – ruakh Sep 24 '12 at 12:11
1

Got it! I have changed the following line:

method = c.getMethod(m, cs);

to:

method = c.getMethod(m, cs.getClass());

Now it works!

Miretz
  • 154
  • 1
  • 12