具有子类类型的通用接口实现

Generic Interface implementation with subclass type

处理器接口:

public interface Processor<T> {

    public void process(T request);

    public Class<T> getRequestType();
}

处理器实现:

public class TextProcessor extends BaseProcessor implements Processor<TextRequest> {

@Override
public void process(TextRequest request) {
    // TODO Auto-generated method stub

}

@Override
public Class<TextRequest> getRequestType() {
    // TODO Auto-generated method stub
    return TextRequest.class;
}

}

请求class:

public class Request {
    private long id;

    ...
}

文本请求

public class TextRequest extends Request {
    String text;
    ...
} 

主要class:

private Map<String, Processor<? extends Request>> processors;

public static void main(String[] args) {

    Processor<?> processor = processors.get("proc name");
    Request request = objectMapper.readValue(json, processor.getRequestType());

    processor.process(request);
}

我在 process 调用中遇到编译错误。

The method process(capture#10-of ?) in the type Processor<capture#10-of ?> is not applicable
for the arguments (Request)

我该如何解决这个问题?

JAVA 编译时检查泛型。

因此,当您编写 Processor<?> processor = processors.get("proc name"); 时,我们不知道如何根据 ? 验证请求。

如果您可以接受 - 尝试使用非通用版本的处理器:

Processor processor = new TextProcessor();

否则可能会为 Processor 接口 (void process(Request request);) 添加一些约束?

所以你有

Processor<?> processor = ...;
Request request = ...;
processor.process(request);

process 被声明为

public void process(T request);

Request 不能保证是 T 的子类型,因此它不会编译。

您需要将 Request 更改为正确的类型。

首先你需要 return 正确的 class 类型。

public Class<?> getRequestType();

变成

public Class<T> getRequestType();

(编辑:现在已在原问题中修改。)

然后我们需要读取一个正确类型的请求对象。对于任何特定的对象 ? 这里将指代特定的类型。我们可以通过引入一种新方法来捕获它。

public static void main(String[] args) {
    doProcess(processors.get("proc name"));
}
private static <T> void doProcess(Processor<T> processor) {
    T request = objectMapper.readValue(json, processor.getRequestType());
    processor.process(request);
}

您在 Processor<?> processor = processors.get("proc name"); 中获得的处理器参数化为未知类型,与 processor.getRequestType() 中的类型没有共同之处。在这种情况下,我不清楚仿制药会给您带来什么好处。似乎您不必知道 main 函数中的具体 Request 子类型是什么,因此无需泛型即可重写所有内容。问题的根本原因是 processors 映射,其中所有处理器都在一个束中。

我可以想象泛型的好处,例如当处理器映射将实现为键类型和值类型之间具有某种相关性的异构映射时。然后 Processor.getRequestType 也必须按类型 T 进行参数化,然后您可以使用:

public static void main(String[] args) {
    Processor<TextRequest> processor = processors.get(TextRequest.class);
    TextRequest request = objectMapper.readValue(json, processor.getRequestType());
    processor.process(request);
}