如何在运行时从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代码中( 例如此处 )。 您只需复制代码并将其重命名为您自己的类。 然后,要在运行时创建表示FooType对象,您可以执行类似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建议。