3

此类来自供应商库:

public class JsonParser {
    public <T> T parse(String json, Class<T> type) { ... }
}

这些是我的模型:

public class Video {
    @Key
    private String title;
    public String getTitle() {
        return title;
    }
}

public class Response<TResult> {
    @Key
    private TResult result;
    public TResult getResult() {
        return result;
    }
    // ...
}

此代码有效:

JsonParser parser = new JsonParser();
String json = "{ \"title\": \"Hello world\" }";
Video video = parser.parse(json, Video.class);

此代码不起作用:(语法错误Response<Video>.class

JsonParser parser = new JsonParser();
String json = "{ \"result\" : { \"title\": \"Hello world\" } }";
Response<Video> videoResponse = parser.parse(reader, Response<Video>.class);

此代码有效:

public class VideoResponse extends Response<Video> {
}

...
JsonParser parser = new JsonParser();
String json = "{ \"result\" : { \"title\": \"Hello world\" } }";
Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);

我的问题是:如何将Response<Video>parse作为参数传递给方法而VideoResponse不像那样创建。(在我的程序中,有很多类似的模型Video,我不想复制我的代码来创建空类VideoResponse,,,,UserResponseCommentResponseActivityResponse

4

2 回答 2

5

由于 Java 泛型的实现方式,在大多数情况下,泛型信息在运行时会丢失。这些所谓的可具体化类型的例外之一是泛型类的具体扩展。对于您的第一个示例:

public class Video {
    @Key
    private String title;
    public String getTitle() {
        return title;
    }
}

public class Response<TResult> {
    @Key
    private TResult result;
    public TResult getResult() {
        return result;
    }
    // ...
}

解析器将无法反序列化该result属性,因为它无法确定它是什么类型(因为此信息在运行时不可用)。基本上,解析只是看到java.lang.Object,并且无法确定实例化的类型以将 JSON 数据拉入。我假设您已经怀疑是这种情况,因此尝试进行此调用:

Response<Video> videoResponse = parser.parse(reader, Response<Video>.class);

在上一行中,您试图告诉解析器特定响应是用 参数化的Video,但不幸的是 Java 没有通用类文字的语法,因此代码无法编译。

在您的第二个示例中:

public class VideoResponse extends Response<Video> {
}

Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);

您已经创建了泛型类的具体扩展。对于此类扩展,通用类型信息在运行时可用,因此您的解析器可以确定它需要实例化什么以反序列化您的 JSON 数据。

所有这些都是您实际问题的背景信息:

我的问题是:如何在不创建 VideoResponse 的情况下将 Response 类作为参数传递给解析方法

您忽略了提及您正在使用的 JSON 库,但在大多数流行的库中,反序列化方法都有一个覆盖版本,该版本接受通常称为超类型令牌的内容。超类型标记基本上只是一个类的具体扩展,类似于我上面描述的。例如,在 Jackson 中,您可以像这样反序列化您的 JSON:

Response<Video> response = new ObjectMapper().readValue(
    jsonString, // JSON data
    new TypeReference<Response<Video>>() {} // super type token, implemented by anonymous class
);

你应该检查你的 JSON 库文档是否有类似的东西。

于 2013-03-24T06:40:49.760 回答
0

由于 Java 泛型类型的“类型擦除”,您应该显式使用类型转换,如下所示:

Response<Video> videoResponse = (Response<Video>) parser.parse(reader, Response.class);

它会引入一个编译警告,但没关系。

于 2013-03-24T06:19:38.127 回答