【问题标题】:How to get Class<List<T>> without an instance of List<T>?如何在没有 List<T> 实例的情况下获取 Class<List<T>>?
【发布时间】:2020-02-05 23:45:48
【问题描述】:

我以前在 Java 中做过这个,但无法访问执行此操作的源代码,我也不记得最初让我得到答案的搜索短语!

我有一个方法需要如下工作..

public <T> List<T> get(String json) {
 return JsonSerializer.deserialize(json, Class<List<T>>);
}

我似乎找到的每个答案都假设我有一个 List 对象,然后我可以使用反射,但在我的情况下我没有。有什么想法吗?

【问题讨论】:

  • 你不能用List.class吗?
  • 你的意思是List.class
  • 不,它不会向反序列化器提供任何关于其试图反序列化的对象的类型信息。
  • A List 在运行时不携带任何类型信息。
  • @MarkCesnik 也许这就是您要找的东西? stackoverflow.com/a/30007018/759049

标签: java


【解决方案1】:

这里有 2 个单独的问题。

第一个问题:您签名中的&lt;T&gt; 完全消除。因此,您想要的(让代码编写,比如说,List&lt;Integer&gt; x = get(someJsonHere); 采用“嘿,此代码明确需要一个整数列表,并在运行时使用它来反序列化 json”的概念是 不可能该信息在运行时不存在。唯一的方法是 API 将是,例如:List&lt;Integer&gt; x = getListOf(Integer.class, someJsonHere)List&lt;Integer&gt; x = getIntList(someJsonHere)

发出第二个:

出于与上述相同的原因,json 反序列化器也不知道该做什么。 java.lang.Class 实例代表类,而不是它们之后的泛型; 不可能用 java.lang.Class 对象来表示“字符串列表”的想法。只有“一个列表”。

因此,就像您提出的 API 不起作用一样,无论“JsonDeserializer”在这里是什么,它的作者都做了一些根本没有破坏的东西,因此为您提供了一种方法来告诉它您想要一个整数或字符串列表或其他具体的。

常见的方式有3种:

[1] 传递其字段已泛化的非泛型类型,因此:

public class YourThing {
    List<String> listOfStrings;
}

并传递YourThing.class

[2] 更多参数!

JsonDeserializer.deserialize(yourJson, List.class, String.class);

[3] 超类型标记。看起来很时髦,但这是合法的 java:

JsonDeserializer.deserialize(yourJson, new JsonDeserializerType<List<String>>() {}); // Note the trailing {}. Required.

查看 json 反序列化器的文档;它会告诉你它提供了哪些策略以及如何具体使用它。

【讨论】:

  • 感谢@rzwitserloot 最终选择了解决方案 #2。
【解决方案2】:

在这种情况下,您可以忽略泛型并使用List.class,它会正常工作。

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModules(new JavaTimeModule());
objectMapper.enableDefaultTyping();
ObjectReader reader = objectMapper.reader();
List<T> data = (List<T>)(objectReader.forType(List.class).readValue(s));

【讨论】:

  • 我的意思是,在方法运行时不会进行类型安全验证,因为泛型通常会确保是验证类型安全的最晚时间。但是这种类型安全无法通过所需的方法签名来验证
  • 这不起作用。序列化器必须知道类 T 以便它可以正确地将 json 数组反序列化为实际对象的列表。这样做会创建一个 Map 对象列表。
  • 你使用什么反序列化器?如果您切换到 Json Jackson 库,它将起作用。我用代码示例更新了答案
  • 您的示例创建了一个不属于 T 类型的 HashMap 列表。所以是的,它确实会反序列化,但是当我尝试访问数据时,它会死得很惨。
  • 我刚刚用objectMapper.enableDefaultTyping();这一行更新了我的答案,看看是否有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2012-07-27
  • 2012-06-16
  • 1970-01-01
相关资源
最近更新 更多