我的目标是开发一个可以输出指定类对象的类。
public class GetMe<T> {
public T get() {
Object obj = generateObject();
return (T) obj;
}
}
现在,我知道由于擦除,这是不可能的。因此,我们可以传入一个类实例并使用它来进行转换。
public class GetMe<T> {
public GetMe<T>(Class<T> clazz) {
this.clazz = clazz;
}
public T get() {
Object obj = generateObject();
return clazz.cast(obj);
}
}
这很棒!只要该类没有参数化。如果是,那我就有问题了。
我不允许使用List<String>.class
。如果我传入ParameterizedType(这本身很难生成),则没有cast
方法可供使用。
有没有摆脱这个泥潭的方法?
答案 0 :(得分:5)
我认为super type tokens可能会为您解决此问题。
答案 1 :(得分:2)
List<String>
的问题在于,由于擦除,它在运行时与任何其他List<?>
无法区分。最简单的方法是创建一个新的类或接口,其通用部分“固定”,如
public interface StringList extends List<String> {
/* nothing to see here */
}
这样你就有了一个类型标记(StringList.class
对象),你可以在运行时传递它并准确指定你想要的东西,但不需要在运行时使用泛型。
答案 2 :(得分:1)
这只是一个小想法。我不确定它是否适合你的背景但是:
public class GetMe<T>
{
public List<T> getList() {
@SuppressWarnings("unchecked")
List<T> result = (List<T>) new LinkedList();
return result;
}
}
干杯!
答案 3 :(得分:0)
第一个问题是您计划如何实例化List
对象。如果您披露了更多您正在尝试构建的内容,我们可能会帮助您做得更好。
您可能希望使用Type而不是Class。类型可以表示所有泛型类型,但使用起来并不愉快。
abstract public class GetMe<T>
{
Type type;
public GetMe<T>(Type type)
{
this.type = type;
}
}
另一个问题是如何创建像List<String>
这样的通用类型。 “超类型令牌”在语法上看起来很整洁,实际上它基本上是
static class XX extends TypeReference<List<String>>{}
....
Type typeListString = Util.extract(XX.class);
我更喜欢这种方式
List<String> f;
Type typeListString = getDeclaredField("f").getGenericType();
实际上,许多这些花哨的运行时通用魔法的框架只在实例字段上工作。
答案 4 :(得分:0)
我认为这种混淆来自于你试图从List<>
创建一个对象,它面对一个接口,而不是一个对象。
所以无论你尝试什么,你都无法创建List<>
的实例,(接口不是实际的类,也没有构造函数)
尝试使用约束来避免在声明中放置接口:
public class GetMe<T extends Object>
这将保证 T 是一个实际的类,而不是一个接口。