I\'ve seen similar questions but they didnt help very much.
For instance I\'ve got this Generic Class:
public class ContainerTest
{
public
There is a way to get the runtime type of the type parameter by using Guava's TypeToken
to capture it. The solution's disadvantage is that you have to create an anonymous subclass each time you need an instance of Container
.
class Container<T> {
TypeToken<T> tokenOfContainedType = new TypeToken<T>(getClass()) {};
public Type getContainedType() {
return tokenOfContainedType.getType();
}
}
class TestCase {
// note that containerTest is not a simple instance of Container,
// an anonymous subclass is created
private Container<String> containerTest = new Container<String>() {};
@Test
public void test() {
Assert.assertEquals(String.class, containerTest.getContainedType());
}
}
The key of this solution is described in tha JavaDoc of TypeToken
's constructor used in the code above:
Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.
If You can define like this
public class ContainerTest<T>
{
public void doSomething(T clazz)
{
}
}
Then it is possible
If you are interested in the reflection way, I found a partial solution in this great article: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
In short, you can use java.lang.Class.getGenericSuperclass()
and java.lang.reflect.ParameterizedType.getActualTypeArguments()
methods, but you have to subclass some parent super class.
Following snippet works for a class that directly extends the superclass AbstractUserType
. See the referenced article for more general solution.
import java.lang.reflect.ParameterizedType;
public class AbstractUserType<T> {
public Class<T> returnedClass() {
ParameterizedType parameterizedType = (ParameterizedType) getClass()
.getGenericSuperclass();
@SuppressWarnings("unchecked")
Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];
return ret;
}
public static void main(String[] args) {
AbstractUserType<String> myVar = new AbstractUserType<String>() {};
System.err.println(myVar.returnedClass());
}
}
The only way is to store the class in an instance variable and require it as an argument of the constructor:
public class ContainerTest<T>
{
private Class<T> tClass;
public ContainerTest(Class<T> tClass) {
this.tCLass = tClass;
}
public void doSomething()
{
//access tClass here
}
}
No. It is not possible because of type erasure (the type parameters are compiled as Object + type casts). If you really need to know/enforce the type in runtime you may store a reference to a Class
object.
public class ContainerTest<T> {
private final Class<T> klass;
private final List<T> list = new ArrayList<T>();
ContainerTest(Class<T> klass) {
this.klass = klass;
}
Class<T> getElementClass() {
return klass;
}
void add(T t) {
//klass.cast forces a runtime cast operation
list.add(klass.cast(t));
}
}
Use:
ContainerTest<String> c = new ContainerTest<>(String.class);
To learn the value of T
you'll need to capture it in a type definition by subclassing ContainerTest:
class MyStringClass extends ContainerTest<String> {}
You can also do this with an anonymous class if you want:
ContainerTest<String> myStringClass = new ContainerTest<String>{}();
Then to resolve the value of T, you can use TypeTools:
Class<?> stringType = TypeResolver.resolveRawArgument(ContainerTest.class, myStringClass.getClass());
assert stringType == String.class;