【问题标题】:Is it possible to send a generic parameter to a Map?是否可以将通用参数发送到地图?
【发布时间】:2011-10-23 19:25:51
【问题描述】:

也许标题措辞不好,知识渊博的人可以编辑它。

我想创建一个方法 parseFromJSONMap,它使用 gson 解析 JSON 文件并将数据作为 Map 返回,更具体地说是 Map<String, T>,其中 T 是名为 Entity 的类的子类。到目前为止已经定义了两个子类,CreatureHero,但以后可能会有更多。所以如果我打电话给

parseFromJSONMap(file, Creature.class)

它应该返回一个Map<String, Creature> 如果我打电话

parseFromJSONMap(file, Hero.class)

它应该返回一个Map<String, Hero> 等。

这就是这个方法现在的样子(它只适用于生物):

public static <T extends Entity> Map<String, T> parseFromJSONMap(File file, Class<T> clazz) throws FileNotFoundException
{
    Type type = new TypeToken<HashMap<String, Creature>>(){}.getType();
    return gson.fromJson(new FileReader(file), type);
}

所以我想输入T,而不是Creature。如果我这样做并这样称呼它

Map<String, Creature> test = Entity.parseFromJSONMap(somefile, Creature.class); 

我收到java.lang.Object cannot be cast to heroes.model.Creature

我想要的可能吗?

编辑:当我在test 上调用任何方法时发生异常,例如test.get("someCreature"),所以这是一个运行时异常。

【问题讨论】:

  • 可能值得添加您获得的堆栈跟踪
  • 我认为这是我得到的唯一例外,因为我所拥有的只是 Creature 中调用 Entity.parseFromJSONMap 的临时 main 方法。 Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to heroes.model.Creature at heroes.model.Creature.main(Creature.java:131)

标签: java json generics gson


【解决方案1】:

你的意思是你这样做是为了让它爆炸?

public static <T extends Entity> Map<String, T> parseFromJSONMap(File file, Class<T> clazz) throws FileNotFoundException
{
    Type type = new TypeToken<HashMap<String, T>>(){}.getType();
    return gson.fromJson(new FileReader(file), type);
}

您的问题是您需要在创建 TypeToken 时使类型参数具体化,否则它怎么知道它应该代表什么类型?请记住,擦除是 replacing type parameters by their leftmost boundsuper type token(这就是 TypeToken 是什么,在 Guice & Gson 和其他各种地方使用)基本上是一个技巧,可以让您通过以下方式访问超类的参数化类型信息反射。还要注意 javadoc 说的

此语法不能用于创建具有通配符的类型文字 参数,如Class&lt;?&gt;List&lt;? extends&gt; CharSequence&gt;

这基本上是你的情况。我知道的唯一出路是以编程方式创建类型令牌。例如,通过Method.getGenericReturnType 或通过查看 Guice 使用类型标记的方式,乍一看它有一套更丰富的实用方法来解决这些问题。如何做到这一点的一个例子是在this question 中,它使用了一些 guice 类,但如果你查看 guice 源,它应该会变得相当明显。

【讨论】:

  • 我不想包含不必要的库。如果我让parseFromJSONMap 成为一个抽象方法,在 Entity 中返回一个普通的 Map,然后让每个子类实现它,会更有意义吗?
  • 这将是一种简单但冗长的解决问题的方法,前提是您将始终控制您正在创建的类型。唯一的选择似乎是扩展您使用的库以提供此功能。
  • 我想这是我想要一个“抽象静态”修饰符的场合之一。我通过拥有一个启动所有内容的 GameResourceManager 类暂时解决了这个问题。 GRM首先解析生物文件夹中的每个json文件来代表生物,然后在英雄文件夹中代表英雄等。我不知道这是否是一个好的设计,但它将责任从单个类转移到单个类类,在那里我可能会更好地控制我正在创建的类型,就像你说的那样。
猜你喜欢
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-06
  • 2022-12-03
  • 1970-01-01
相关资源
最近更新 更多