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