假设泛型类型声明(Java)
class Foo<T> {
public T bar;
}
我怎样才能在运行时实例化一个Type对象,该对象表示通过特定类型T参数化的Foo(也仅在运行时知道)?
答案 0 :(得分:13)
我想我理解你的问题。您希望序列化Foo<T>
,并且在运行时具有T
的类对象(但在编译时它没有修复)。因此,在Gson中建议的创建TypeToken
的匿名子类的解决方案不起作用,因为这要求参数化类型(例如Foo<String>
)在编译时被硬编码,并且如果你使用像Foo<T>
这样的东西。
但是,让我们看一下Gson网站上TypeToken
方法实际完成的内容。您创建了TypeToken
的匿名子类的对象,然后使用其getType()
方法请求其类型参数。类的超类是其元数据的一部分,包括其超类的泛型参数。因此,在运行时,它可以查看自己的继承层次结构,并找出用于TypeToken
的类型参数,然后返回该类型的java.lang.reflect.Type
实例(如果参数化,将返回是一个ParameterizedType
实例)。获得此Type
实例后,您应该将其作为toGson()
的第二个参数传递。
我们需要做的就是找到另一种方法来创建ParameterizedType
的这个实例。 ParameterizedType
是一个接口,但不幸的是,公共Java API没有提供任何具体的实现或任何方式来动态创建ParameterizedType
。似乎有一个名为ParameterizedTypeImpl
的类,在私有Sun API和Gson代码中可以使用(e.g. here)。您只需复制代码并将其重命名为您自己的类。然后,要在运行时创建表示Type
的{{1}}对象,您可以执行Foo<String>
(未经测试)
答案 1 :(得分:4)
我们假设我们正在谈论List<String>
。
你可以构建这样的东西:
Type type = new ParameterizedType() {
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
public Type[] getActualTypeArguments() {
return new Type[] { String.class};
}
};
如果您需要使用此功能从JSON反序列化,则可以使用此Type
来调用gson.fromJson
答案 2 :(得分:2)
关于类型擦除的常用方法是:
class Foo<T> {
Class<T> clazz;
public Foo(Class<T> c) {
clazz = c;
}
public T bar {
return clazz.newInstance();
}
}
如果你的T没有no-args构造函数,你可以使用Class对象的反射来做更好的事情;一旦你有一个Class<T>
的实例,你就可以获得一个实例。
我和gson也面对这个问题。我最终得到了这个:
public class JsonWrapper {
private String className;
private String json; // the output of the gson.toJson() method
}
当我需要反序列化时,我做了Class.forName(className)
然后我需要调用gson库的fromJson()方法。
我简直不敢相信gson本身不支持这一点 - 想要这样做是显而易见的事情......得到一些json并将其变成一个对象而不用知道哪个类它是事先。
答案 3 :(得分:-1)
Gson确实为此提供了解决方案:https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener
当然这只是波希米亚的解决方案(你还需要以某种方式传递类型参数),但是会自动完成。
答案 4 :(得分:-1)
其他人说的话:)。要实例化的类需要在运行时可用。许多方法:将类或类名放在工厂的本地变量中,使用受保护的方法,如果需要在许多不同的地方执行此操作,则创建“对象工厂”类等。这是一种bean框架所做的工作,所以如果你正在使用它,可以通过配置它来实现。
答案 5 :(得分:-2)
它似乎比大多数人想象的要简单得多:
Type collectionType = new TypeToken<ArrayList<Person>>(){}.getType();
ArrayList<Person> persons = gson.fromJson(response, collectionType);
无需将ParameterizedTypeImpl类复制为newacct建议。