How does one get a parameterized Class object to be used as a method argument?
class A<T>
{
public A(Class<T> c)
{
}
void main()
{
A<String> a1 = new A<String>(String.class); // OK
A<List<String>> a2 = new A<List<String>>(List<String>.class); // error
A<List<String>> a3 = new A<List<String>>(Class<List<String>>); // error
}
}
Why do I want to do that, you may ask? I have a parameterized class whose type is another parameterized class, and whose constructor requires that other class type as an argument. I understand that runtime classes have no information on their type parameters, but that shouldn't prevent me from doing this at compile time. It seems that I should be able to specify a type such as List<String>.class
. Is there another syntax to do this?
Here is my real usage case:
public class Bunch<B>
{
Class<B> type;
public Bunch(Class<B> type)
{
this.type = type;
}
public static class MyBunch<M> extends Bunch<List<M>>
{
Clas开发者_如何转开发s<M> individualType;
// This constructor has redundant information.
public MyBunch(Class<M> individualType, Class<List<M>> listType)
{
super(listType);
this.individualType = individualType;
}
// I would prefer this constructor.
public MyBunch(Class<M> individualType)
{
super( /* What do I put here? */ );
this.individualType = individualType;
}
}
}
Is this possible?
How about just cast?
super((Class<List<M>>)List.class);
Class literals are not going to have the type parameters that you want.
Remember you will NOT get a List as a class in runtime, and the right approach would probably be using TypeToken as BalusC told you. Without TypeToken, you can't cast to List, but you can create something like this:
public static class MyBunch2<List_M extends List<M>, M> extends Bunch<List_M>
{
Class<M> individualType;
@SuppressWarnings("unchecked")
public MyBunch2(Class<M> individualType)
{
super((Class<List_M>) List.class);
this.individualType = individualType;
}
}
Since List_M extends List<M>
this is not as typesafe as you may wish, but maybe is nice enough. Creating an instance will be as ugly as writing
MyBunch2<List<String>, String> a = new MyBunch2<List<String>, String>(String.class);
but you can improve it with a factory method
public static <M2> MyBunch2<List<M2>, M2> of(Class<M2> individualType){
return new MyBunch2<List<M2>, M2>(individualType);
}
and then write
MyBunch2<List<String>, String> b = MyBunch2.of(String.class);
If you are using eclipse, code assist will help you writing the ugly class MyBunch2, String>
Of course, in runtime, this.type will be java.util.List, not java.util.List To get it right, go for TypeToken.
---Continuation---
You can even make another class
public static class MyBunch3<M> extends MyBunch2<List<M>, M>
{
public MyBunch3(Class<M> individualType) {
super(individualType);
}
}
And then create instances as
MyBunch3<String> c = new MyBunch3<String>(String.class);
There must be a way to do that in just one class...but I can't figure it out
精彩评论