Is it possible in Java to find out the general collector type using reflection?

I have a class with a collector that I traverse through reflection. Something like that:

class Bar {
  String baz;
  int bazooka;
}
class Foo {
  List<Bar> bars = new ArrayList<Bar>();
  List<Bar> getBarsList() { return bars; }
}

      

What I need to find out at runtime is the class object Class<Bar>

. I know this is possible if you have an object reference Field

. But is it possible from a getter too Method

?

+3


source to share


2 answers


Reflection can be used in your case. What you cannot do is get runtime type information. Given an instance of a parameterized type, you cannot know at runtime what it was parameterized with. This is what the other answers tell you, but not what you ask. You are asking for compile-time type constraints.

public class Test {

  public static void main(String args[]) throws NoSuchMethodException {
    Method method = Foo.class.getDeclaredMethod("getBars", new Class[]{});
    Type grt = method.getGenericReturnType();
    if (grt instanceof ParameterizedType) {
      Type Bar = ((ParameterizedType) grt).getActualTypeArguments()[0];
      System.out.println(Bar);
    }
  }
}

class Foo {
  List<Bar> getBars() {
    return Collections.emptyList();
  }
}

class Bar {
}

      

Printing class com.package.Bar



If, on the other hand, you had a class like this:

class Foo<T> {
  List<T> getBars() {
    return Collections.emptyList();
  }
}

      

Then you couldn't get T for the Foo instances at runtime. There are workarounds where people create anonymous subclasses with a fixed type parameter.

+4


source


This information is missing at runtime for two reasons:

1) He is not needed there. This is a compiler hint and a match for your strong input methods.

2) Java uses generic type erasure to maintain compatibility with pre-generic types.

You can do this one at a time (dumb, but will work if the code is yours):



class MyGenericClass extends ArrayList<MyObject> {

     // Check the class for this variable name. Its type will indicate the generic type.
     // Alternatively we can use the type class instance directly.
     final static MyObject mGenericType      = null; 
     final static Class    mGenericTypeClass = MyObject.getClass();

} 

      

I understand that a partial solution (if any solution at all), but still, is better than nothing if you really need it .

On the other hand, there is an easy way to do it. You can do persistent annotation with an argument that will provide information about the general type of the annotated class / field.

+1


source







All Articles