标题名称可能措辞不当,并且知识渊博的人可以对其进行编辑。

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

parseFromJSONMap(file, Creature.class)


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

parseFromJSONMap(file, Hero.class)


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

这就是现在的方法(仅适用于Creatures):

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);
}


因此,我想放置Creature而不是T。如果我这样做并这样称呼它

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


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

我想要什么?

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

最佳答案

您是说要这样做才能使它炸毁吗?

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时需要使type参数具体化,否则如何知道它应该表示什么类型?请记住,擦除是replacing type parameters by their leftmost bound,而super type token(这是TypeToken的含义,在Guice&Gson和其他地方使用)基本上是一种技巧,使您可以通过以下方式访问超类的参数化类型信息反射。还要注意javadoc说


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


这基本上是您的情况。我知道的唯一出路是通过编程方式创建类型令牌。例如,通过Method.getGenericReturnType或通过查看Guice使用类型令牌的方式,乍一看,它具有一组更丰富的实用程序方法来弄清楚这些内容。如何执行此操作的示例在this question中,该示例使用了一些guice类,但是如果您查看guice源,那么正在发生的事情应该变得相当明显。

09-28 03:50