启动动态类型的ArrayList

时间:2017-03-21 14:08:56

标签: java list serialization gson deserialization

我有一个HTTP请求处理程序,它返回一个Sub FilterCstomers() Dim f As String: f = InputBox("Type the text you want to filter:") With Sheets("Customers Pivot").PivotTables("Customers_PivotTable") .ClearAllFilters .PivotFields("Concatenation for filtering").CurrentPage = "*f*" End With End Sub 反序列化的JSON,它派生自一个抽象Object,然后转换为正确的类。我有一些问题使这个处理程序返回Request

List

如果public class ListMyResource extends AbstractRequest { public boolean isCollection; public ListTransactions() { this.isCollection = true; } public final RequestMethod REQUEST_METHOD = RequestMethod.GET; public final String URL_METHOD = ""; public Class<ArrayList<MyResource>> getResourceClass() { return new ArrayList<MyResource>().getClass(); } } public Object getDeserializedResponse() { Response response = new Response(this.request, true); try { if (this.request.isCollection()) { List<this.request.getResourceClass()> list = new ArrayList<this.request.getResourceClass()>(); listType = new TypeToken<ArrayList<AbstractObject>>() { }.getType(); response.setData(deserialize.fromJson(this.getResponse(), listType)); } else { response.setData(deserialize.fromJson(this.getResponse(), this.request.getClazz())); } } catch (JsonSyntaxException jse) { MyLibrary.LOG.error("Could not parse JSON", jse); response.setRequestWasSuccessfull(false); } return response; } 返回false,并且该方法只需要提供一个反序列化的对象,上面的代码就可以正常工作,但它不能用于集合,因为我无法将结果放在来自列表中isCollection()的{​​{1}}。这导致getResourceClass()。我如何处理这个问题,以便达到预期的效果?

1 个答案:

答案 0 :(得分:1)

  

ArrayList<this.request.getResourceClass()>

这不起作用。 Java类型参数必须是编译时&#34;常量&#34; (我的意思是,编译器已知的东西)。所以,

List<String> strings

是类型参数的有效语法,但

List<some.runtime.expression.here()>

不是。接下来,我强​​烈建议您不要使用Class<?>来传递数据类型信息。请注意,Class<?>包含有关系统中真实类型的信息。考虑你想要一个字符串列表,一个整数列表和一个布尔类型列表。你不能ArrayList<String>.class - 它是Java中的非法表达,因为实际的类型参数不是类信息的一部分。你能用ArrayList之类的东西继承extends ArrayList<String>吗?你可以,但你不应该。如果子类的类别为final或您要使用LinkedList怎么办?某种代码臃肿,不是吗?

Classjava.lang.reflect.Type,Gson要求将后者的实例传递给fromJson()方法。如果你自己构建它怎么办? Gson提供了一种方便的机制来构造java.lang.reflect.Typejava.lang.reflect.ParameterizedType(后者在Gson中非常集中地用于集合,详见Gson TypeToken s)。有两种方式:

  • TypeToken.getParameterized(rawType, typeParameter1, typeParameter2)

例如,TypeToken.getParameterized(List.class, String.class).getType()将返回ParameterizedType实例,就像您可以编写List<String>.class一样。这是一种真正的动态方法,您可以将一些运行时执行结果传递给getParameterized()方法。

  • TypeToken子类化

这里的诀窍是TypeToken是一个抽象类,它可以参数化,让Gson在运行时分析一个通常是匿名的类来获取实际参数,让getType()方法返回一个编译时组合类型:new TypeToken<List<String>>(){}.getType()(子类可以存储有关其超类参数化的信息,Gson在运行时使用它)。请注意,getRawType仅返回List.class - 这就是Java泛型的实现方式,因为Class无法存储实际的类型参数(请阅读Java generics and erasure的更多信息)。

考虑到这个模糊的解释,只需重构您的getDeserializedResponse()方法,使请求返回java.lang.reflect.Type而不是Class<?>。我甚至认为您可以从该方法中删除isCollection并让Gson自行完成所有操作:Gson 可以区分List<String>List<Integer>类型。