Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get class of generic type when there is no parameter of it?

Tags:

java

generics

I just learned about this fine looking syntax

Collections.<String>emptyList()

to get an empty List with elements which are supposedly of type String. Java's source looks like this:

public static final List EMPTY_LIST = new EmptyList<Object>();
:
public static final <T> List<T> emptyList() {
  return (List<T>) EMPTY_LIST;
}

Now if I code a method in that way where the generic type does not appear in the parameter list, is there any way how I can access the actual class that becomes T?

I'm saying, up to now my approach to code the same thing would have been

private <T> T get(String key, Class<T> clazz) {
  // here I can do whatever I want with clazz, e.g.:
  return clazz.cast(value);
}

If I removed the clazz-parameter I wouldn't be able to do the cast(). Obviously I could do

  return (T) value;

but that gives me the usual warning Type safety: Unchecked cast from Object to T. Ok, @SuppressWarnings("unchecked") helps here, but actually I want to do something with the intended return type of the method. If I add a local variable

T retValue;

I'd have to initialise it with something, null doesn't help. After I assign it like

@SuppressWarnings("unchecked")
T retValue = (T) value;

I could do, e.g.

retValue.getClass().getName()

but if the cast fails I end up with no information about T again.

Since Java (or at least my Java 6) does not have the generic info any more during runtime, I currently can't think of a way to do this. Is there a way? Or do I have to stick with my "old" approach here?

Please note that the example I lined out is very simple and doesn't make much sense. I want to do more complicated stuff here, but that's out of the scope.

like image 545
sjngm Avatar asked Dec 08 '11 18:12

sjngm


People also ask

How do you find the class of a generic type?

You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass. of(String. class) .

How do I get a class instance of generic type T?

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details. A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

Can a non generic class have a generic method?

Yes, you can define a generic method in a non-generic class in Java.

Can a non generic class inherit a generic class?

Yes, in this case, inheritance is a better solution than composition as you have it, because a StackInteger is a Stack .


2 Answers

If you want the generic type at runtime you need to either have it as a field or create a sub-class of a type for a specific combination of types.

e.g.

List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
final Class type = (Class) ((ParameterizedType) list.getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);

prints

class java.lang.String
like image 120
Peter Lawrey Avatar answered Oct 24 '22 03:10

Peter Lawrey


You can't, unfortunately. All generics and type parameters are erased in runtime. So in runtime the type of your T is simply Object

like image 42
korifey Avatar answered Oct 24 '22 02:10

korifey