1

I need to find if my current class has method with a parameter that either its type is Integer of its generic type is Integer.

I wrote the following in main:

public static main(String[] args){
   Class<?> clazz = Class.forName("Test");
   Class<?> lookingForClass = Integer.class;
   Method[] method = clazz.getMethods();
   for (int i = 0; i < method.length; i++) {
       Type[] types = method[i].getGenericParameterTypes();
       for (int j = 0; j < types.length; j++) {
           Type type = types[j];
           Class<?> result = type.getClass();
           if (type instanceof ParameterizedType) {
               ParameterizedType pt = (ParameterizedType) type;
               Type[] fieldArgTypes = pt.getActualTypeArguments();
               result = (Class<?>) fieldArgTypes[0];
           }
           if (result instanceof lookingForClass)
               System.out.println("found it");
           }
      }
}

public static void findTowInArray(List<Integer> A) {

}

public static void findTowInArray(Integer A) {

}

public static void findTowInArray(String A) {

}

However I get a compilation error on if (result instanceof lookingForClass)

Incompatible conditional operand types Class<capture#6-of ?> and lookingForClass

What is wrong?

Aleks G
  • 56,435
  • 29
  • 168
  • 265
Dejell
  • 13,947
  • 40
  • 146
  • 229
  • 2
    You possibly meant: `if (result.isAssignableFrom(lookingForClass))`? – assylias Jun 10 '13 at 10:33
  • See [this answer](http://stackoverflow.com/questions/11751550/java-instanceof-operator) – Anders R. Bystrup Jun 10 '13 at 10:33
  • @assylias it works only for findTowInArray(List A) and not for findTowInArray(Integer A) as type.getClass() in the second method returns class – Dejell Jun 10 '13 at 10:37
  • 1
    @assylias I think the right way is `lookingForClass.isAssignableFrom(result)` – Aleks G Jun 10 '13 at 10:39
  • @AndersR.Bystrup I tried to write if (result.isInstance(lookingForClass)) but it would work return true only if the parameter type is List. Since if it's Integer, Class> result = type.getClass(); returns Class and not Integer. How can I get the Integer from type if it's not parameterized? – Dejell Jun 10 '13 at 10:40
  • @AleksG it still doesn't work for me as it doesn't find findTowInArray(Integer A) which is also valid – Dejell Jun 10 '13 at 10:44
  • `lookingForClass.isAssignableFrm(result)` will check if `result` is a subclass of `Integer`. If you need specifically `Integer` and not any of its subclasses, you can then use `if(result.equals(lookingForClass))` – Aleks G Jun 10 '13 at 10:56
  • Thanks. I answered my question based on all of your comments. – Dejell Jun 10 '13 at 11:01

4 Answers4

1

If a Type is already a class don't call getClass() on it.

public static void main(String[] args) throws ClassNotFoundException{
    Class<?> clazz = Class.forName("Test");
    Class<?> lookingForClass = Integer.class;
    Method[] methods = clazz.getMethods();
    for (int i = 0; i < methods.length; i++) {
        Method method = methods[i];
        Type[] types = method.getGenericParameterTypes();
        for (int j = 0; j < types.length; j++) {
            Type type = types[j];
            Class<?> result = type instanceof Class<?> ? (Class<?>)type : type.getClass();
            if (type instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) type;
                Type[] fieldArgTypes = pt.getActualTypeArguments();
                result = (Class<?>) fieldArgTypes[0];
            }
            if (result.equals(lookingForClass))
                System.out.println("found " + method);
            }
       }
 }

And I would prefer loops like

for (final Method method : methods) {
    ...
}

if you don't need the index.

bebbo
  • 2,830
  • 1
  • 32
  • 37
0

Please try using below code, you have to compare type and Integer.class

public static void main(String[] args) throws ClassNotFoundException
    {
        Class<?> clazz = Class.forName("Test");
        Class<Integer> lookingForClass = Integer.class;
        Method[] method = clazz.getMethods();
        for (int i = 0; i < method.length; i++)
        {
            Type[] types = method[i].getParameterTypes();

            for (int j = 0; j < types.length; j++)
            {
                Type type = types[j];
                Class<?> result = type.getClass();
                if (type instanceof ParameterizedType)
                {
                    ParameterizedType pt = (ParameterizedType) type;
                    Type[] fieldArgTypes = pt.getActualTypeArguments();
                    result = (Class<?>) fieldArgTypes[0];
                }
                if (type ==  lookingForClass)
                    System.out.println("found it");
            }
        }
    }
Pritesh Shah
  • 857
  • 1
  • 7
  • 8
  • I should get found it twice, but get it only once. It doesn't work – Dejell Jun 10 '13 at 10:52
  • `type == lookingForClass` will not work, as you are comparing memory addresses. – Aleks G Jun 10 '13 at 10:59
  • Generally yes, but in this case not right, see: [Java equals for a Class. Is == same as .equals](http://stackoverflow.com/questions/7322469/java-equals-for-a-class-is-same-as-equals) – mrak Jun 10 '13 at 11:07
0

Gathering all the comments above, the solution was to do:

if (lookingForClass.isAssignableFrom(result) || type.equals(lookingForClass))
    System.out.println("found it");

and not

if (result instanceof lookingForClass)
Dejell
  • 13,947
  • 40
  • 146
  • 229
0

You can't get the type because of Type Erasure. Java compiler will "Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded". For example:

public class Test<T> {
    public void setT(T t) {}
}

compiles to

public class Test {
    public void setT(Object t) {}
}

So it is not possible to get the type information at runtime. See also related question: Get the generic type of an extending generic class in the constructor of the superclass in Java?

Community
  • 1
  • 1
mrak
  • 2,826
  • 21
  • 21