【问题标题】:How do I correctly use generics?如何正确使用泛型?
【发布时间】:2010-12-28 06:43:34
【问题描述】:

我基本上是在发出网络请求并接收 JSON 响应。根据请求,我将 JSON 请求解析为我创建的对象。无论我解析成什么样的对象,解析几乎都是一样的。所以我有一堆方法只对不同的对象做同样的工作,我想知道我怎么能用泛型来完成这个?这是一个例子

   public static ArrayList<Contact> parseStuff(String responseData) {
ArrayList<Person> People = new ArrayList<Person>();
try {

    JSONArray jsonPeople = new JSONArray(responseData);
    if (!jsonPeople.isNull(0)) {
        for (int i = 0; i < jsonPeople.length(); i++) {
            People.add(new Person(jsonPeople.getJSONObject(i)));
        }

    }

} catch (JSONException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (Exception e) {

}

return People;

}

【问题讨论】:

  • 您可能不想使用泛型。您正在解析多少个不同的对象?解析每个对象的代码是否相同?
  • 是的,除了对象不同,代码基本相同,所以在我发布的示例中,我有完全相同的方法,只是你可以将联系人对象替换为人员对象
  • 你需要返回多少个不同的类类型。
  • 每次运行这个方法,只会返回一个类类型

标签: java android json generics


【解决方案1】:

你应该看看Effective Java 2, Item 29: Consider typesafe heterogeneous type containers

基本思想是你可以想象你有一些Deserializer 接口。然后你可以有一个Map&lt;Class&lt;?&gt;, Deserializer&lt;String, Object&gt;&gt;。该映射基本上是从类型到该类型的正确Deserializer 的注册表(它从字符串反序列化(也许您想要一个 json 类型或其他东西而不是字符串,但字符串有效)到感兴趣的类型。

真正的诀窍是您必须强制类键类型与反序列化器类型匹配。即 - 对于作为映射中键的某些类,您有一个反序列化器作为值。您可以使用通用方法执行此操作。例如:

<T> void put(Class<T> clazz, Deserializer<String, T> deserializer) {
  map.put(clazz, deserializer);
}

那么要使用异构映射,可以再次使用泛型方法:

<T> T deserialize(Class<T> typeToDeserializeFromJson, String toDeserialize) {
  return typeToDeserializeFromJson.cast(
      deserializers.get(tTDFJ).deserialize(toDeserialize));
}

您使用方法调用者指定的类型来

  • 查找正确的`Deserializer`
  • 将 json 文本反序列化为“对象”
  • 安全地将 `Object` 转换为正确的类型,我们知道这是安全的,因为我们最初是如何构建地图的。

我希望我所说的至少有点清楚。阅读 EJ2 中的相应条目应该会有所帮助!

更新:

As Abhinav points out,GSON 库将帮助您以适当使用泛型的方式完成反序列化对象的最终目标。但是,我认为您的问题更多是关于泛型而不是最终目标,所以我觉得我的回答更合适。 GSON 必须使用异构类型的容器来实现 :-)。

感谢Abhinav 指出 GSON!

【讨论】:

  • 如果我去掉DeserializerString 类型,也许这个例子会更清楚。我的意图是 Deserializer&lt;F, T&gt; 将 F 类型的对象反序列化为 T 类型的对象。
  • 如果你有一个异构容器,你会怎么做? GSON 如何知道要使用哪个反序列化?你可以设置它来查看属性来决定吗?
【解决方案2】:

我建议您使用 GSON 而不是 JSON。它确实简化了您的生活。

【讨论】:

  • gson 必须以类似于我建议的方式实现。 (需要一个类型安全的异构容器,调用反序列化方法时指定类型也是必要的)。
  • 另外,我想知道是否会有依赖于 gson 的问题,因为它被标记为 Android。
  • Gson 为您处理内部事务。你只需要说类似 - “(new Gson()).fromJson(numbersText, PhoneStatus.class)”。
  • 我并不是说它不适用于 Android —— 我是说开发移动应用程序的人有时会回避第三方库,因为它们很容易避免。虽然从我的快速浏览来看,它似乎并不太重量级。
  • 是的,有时候开发者太不情愿是很遗憾的——特别是 org.json 包非常原始,以至于使用适当的 JSON 库(Gson、Jackson、json-lib)会大大简化生活大多数情况下。
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
相关资源
最近更新 更多