将参数化类型作为参数传递给方法

Jac*_*Dam 3 java generics reflection

这个类来自供应商库:

public class JsonParser {
    public <T> T parse(String json, Class<T> type) { ... }
}
Run Code Online (Sandbox Code Playgroud)

这些是我的模型:

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;
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

此代码有效:

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

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

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

此代码有效:

public class VideoResponse extends Response<Video> {
}

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

我的问题是:如何将Response<Video>parse作为参数传递给方法而VideoResponse不像那样创建。(在我的节目,也有类似的许多车型Video,我不想重复我的代码来创建空类VideoResponseUserResponseCommentResponseActivityResponse,等)

Per*_*ion 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;
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

Response<Video> videoResponse = parser.parse(reader, Response<Video>.class);
Run Code Online (Sandbox Code Playgroud)

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

在你的第二个例子中:

public class VideoResponse extends Response<Video> {
}

Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);
Run Code Online (Sandbox Code Playgroud)

您已经创建了泛型类的具体扩展。对于此类扩展,泛型类型信息在运行时可用,因此您的解析器可以确定它需要实例化什么以反序列化您的 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
);
Run Code Online (Sandbox Code Playgroud)

您应该检查您的 JSON 库文档是否有类似的内容。