此类来自供应商库:
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
,UserResponse
,CommentResponse
,{{1} }等等)
答案 0 :(得分:4)
由于Java泛型的实现方式,在大多数情况下,通用信息在运行时会丢失。这些所谓的reifiable类型的例外之一是泛型类的具体扩展。第一个例子:
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没有泛型类文字的语法,因此代码无法编译。 / p>
在你的第二个例子中:
public class VideoResponse extends Response<Video> {
}
Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);
您已经创建了泛型类的具体扩展。对于此类扩展,泛型类型信息在运行时可用,因此您的解析器可以确定实例化所需的内容,以便反序列化您的JSON数据。
所有这些都是您实际问题的背景信息:
我的问题是:如何将Response类作为参数传递给parse方法而不创建像这样的VideoResponse
您忽略了提到您正在使用的JSON库,但在大多数流行的库中,反序列化方法都有一个覆盖版本,它接受通常所说的超类型令牌。超类型令牌基本上只是类的具体扩展,类似于我上面描述的。例如,在杰克逊,您可以像这样反序列化您的JSON:
Response<Video> response = new ObjectMapper().readValue(
jsonString, // JSON data
new TypeReference<Response<Video>>() {} // super type token, implemented by anonymous class
);
您应该检查JSON库文档中的类似内容。
答案 1 :(得分:0)
由于Java泛型类型的“类型擦除”,您应该明确使用类型转换,如下所示:
Response<Video> videoResponse = (Response<Video>) parser.parse(reader, Response.class);
它会引入编译警告,但没关系。