2

I'm using reflection to walk the field members of a class and I need to know for List<> subclasses, what the generic type parameters are.

Given a field that has a type that is a subclass of List, how can I tell in a generic way what the type parameters of List<> are?

For example:

class X<T> {
   List<String> x1; // String
   ArrayList<String> x2; // String
   SubclassOfArrayListString x3; // String
   List<?> x4; // error
   List<T> x5; // error
}

class SubclassOfArrayListString extends ArrayList<String> {
   // ...
}

NOTE: I added <T> to X above to illustrate that there might be cases where there isn't a correct answer - it has nothing to do with the problem, except being something to consider when answering.

slipheed
  • 7,170
  • 3
  • 27
  • 38
  • 2
    possible duplicate of [Get generic type of java.util.List](http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list) – BalusC Aug 30 '11 at 18:27
  • So do you want something like this? x1 -> [class java.lang.String], x2 -> [class java.lang.String], x3: class SubclassOfArrayListString, x4 -> [?] (WildcardType), x5 -> [T] (TypeVariable) – Philipp Reichart Aug 30 '11 at 19:08
  • Philipp: x3->String, x4/x5 are "undefined", so as long as I can determine that they have no full type yet, that's fine. – slipheed Aug 31 '11 at 01:44

3 Answers3

1

You can't because generic type information is lost on compilation (*). That's also the reason you cannot create an array of some generic type T at runtime.

At runtime, every List<T>is again a raw type List -- you could even add an Integer to something declared as List<String>, generics won't and can't prevent that [Edit: using unchecked casts or a widening cast to a raw type; this will result in (suppressable) compiler warnings but no errors].

(*) Edit: I learned some new and stand corrected, certain type parameters (implementors of GenericDeclaration like Class, Constructor, Field and the return, parameter and exception types of Method) will be retained in the byte code and can be accessed at runtime using Field.getGenericType() and similar accessors.

Philipp Reichart
  • 20,771
  • 6
  • 58
  • 65
  • 3
    Sorry, that's not actually true for generic types. f.getGenericType() returns the parameterized type, ie: java.util.List – slipheed Aug 30 '11 at 18:29
  • 2
    @Saher Yes, not directly but using an unchecked cast or widening cast to a raw type `List` (a mistake easily made) you could in fact add anything to any `Collection` without the compiler preventing it -- it would only warn and even that can be suppressed. – Philipp Reichart Aug 30 '11 at 18:35
  • @slipheed I didn't know that. But couldn't you then just call `getGenericType()` on the `Field`s of the class you reflect on? – Philipp Reichart Aug 30 '11 at 18:42
  • @Philipp, yeah, but I'm not sure what the right technique is to walk up the chain of supertypes. I was hoping this had been solved before. – slipheed Aug 30 '11 at 18:45
0
public class X<T extends List> {
  T field;
}

Is that what you need?

jFrenetic
  • 5,384
  • 5
  • 42
  • 67
0

Read this tutorial about Generics : Generics Tutorial. This should clear things up.

This pdf has also good examples at the end of the wildcard usage as well as the extends ans super keywords. PDF Doc

Basically, Use Container<? extends A> when you want to read from the container Use Container<? super A> when you want to write to the container.

Saher Ahwal
  • 9,015
  • 32
  • 84
  • 152