0

In java, I get can get the type of any class using ClassName.class. But what if I want to get the type of a parametarized(generic) collection? Collection<MyClass>.class does not work.

This is what I want to do:

ParameterExpression<Collection<MyClass>> dateParameter = criteriaBuilder.parameter(Collection<MyClass>.class);
Piotr
  • 4,813
  • 7
  • 35
  • 46

2 Answers2

4

Due to how generics are implemented in Java (type erasure), there is no Collection<MyClass> class. Just the standard Collection class.

Generics are effectively extra compile-time checks which only make it into the generated bytecode in a limited fashion. In particular, objects do not know with which generic parameters they were instantiated, so you can't call e.g. instanceof at runtime to check this.

Most reflective calls (which includes use of the Class class) overlook generics, because you wouldn't get any type safety anyway. Even if the runtime allowed you to access the Collection<MyClass> class, its add method would still take merely Object since this would just be syntactic sugar for getting the raw type Collection. Java arguably makes the correct decision here by not allowing this potentially misleading syntax, so as it make it clear that generic classes don't actually exist at runtime.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • Andrzej: Ok thank you. How would you solve the problem above? (question updated). Just suppress the warning? – Piotr Mar 22 '11 at 08:40
  • Yeah, unfortunately you can either suppress the warning or use double casting (cast to the raw type `Class` and then back down to `Class>`) to get this to compile without errors. Don't forget that not all warnings are necessarily bad - it's just the compiler saying "I can't tell if this is correct or not". Situations like this, where it's obvious to the developer (but not the compiler) that this is correct, is what warning suppression was made for. – Andrzej Doyle Mar 22 '11 at 08:45
0

Acquiring generic class type

public static <C extends Collection, E, T extends Collection<E>>
Class<T> cast(Class<C> classC, Class<E> classE)
{
    return (Class<T>)classC;
}

Class<Collection<MyClass>> clazz = cast(Collection.class, MyClass.class)
criteriaBuilder.parameter( clazz );

However, since only the raw class is passed at runtime, the library won't be knowledgeable about the detailed type, which might be neeed to do the job.

Such library should expand to accept Type which includes richer type info. The question now becomes how to write the Type of <Collection<MyClass>> at compile time. "Super Type Token" is one way.

Community
  • 1
  • 1
irreputable
  • 44,725
  • 9
  • 65
  • 93