我有以下情况:
public interface BaseConfig {
}
public abstract class BaseWidget<C extends BaseConfig> {
public abstract C getConfig();
public abstract void setConfig(C config);
public abstract Class<C> getConfigClass();
}
public class ConcreteConfig implements BaseConfig {
public String foo = "bar";
}
public class ConcreteWidget extends BaseWidget<ConcreteConfig> {
private ConcreteConfig config;
public ConcreteWidget(ConcreteConfig config) {
this.config = config;
}
@Override
public ConcreteConfig getConfig() {
return config;
}
@Override
public void setConfig(ConcreteConfig config) {
this.config = config;
}
@Override
public Class<ConcreteConfig> getConfigClass() {
return ConcreteConfig.class;
}
}
我希望能够将BaseConfig
的实例一般序列化和反序列化为BaseWidget
实现指定的正确类型。以下作品:
final BaseWidget<ConcreteConfig> instance = new ConcreteWidget(new ConcreteConfig());
final BaseConfig config = instance.getConfig();
final String configJson = om.writeValueAsString(config);
instance.setConfig(om.readValue(configJson, instance.getConfigClass()));
现在如果我尝试使上面的代码通用(消除ConcreteConfig
的出现,所以第一行的类型为BaseWidget<? extends BaseConfig>
),我在最后一行得到以下编译错误:< / p>
错误:(18,40)java:不兼容的类型:BaseConfig无法转换为捕获#1的?扩展BaseConfig
或在IntelliJ中:
BaseWidget中的setConfig(capture&lt;?extends BaseConfig&gt;)无法应用于(捕获&lt;?extends BaseConfig&gt;)
我知道错误告诉我两个捕获是不兼容的,但为什么会这样?据我所知,instance.setConfig(C)
和instance.getConfigClass() -> Class<C>
的类型必须生成相同的C
,因为它们来自同一个实例。
我可以通过BaseWidget
使用其他方法代替setConfig
来解决此问题。
public abstract void readConfig(ObjectMapper mapper, String rawConfig) throws IOException;
并在ConcreteWidget
:
@Override
public void readConfig(ObjectMapper mapper, String rawConfig) throws IOException {
this.config = mapper.readValue(rawConfig, ConcreteConfig.class);
}
但我宁愿不让小部件依赖任何序列化逻辑。
这是我的测试专家项目:https://drive.google.com/open?id=16zt2FC8Gs5Cke-kbYBDRhmytE5utVn8E
答案 0 :(得分:0)
另一项工作如下:
final BaseWidget<ConcreteConfig> instance = new ConcreteWidget(new ConcreteConfig());
答案 1 :(得分:0)
为了说服编译器两个类型C
是相同的,我需要为上面的操作引入一个类型名称。在我的情况下,将代码提取到这样的方法就可以了:
private static <C extends BaseConfig> void parseSetConfig(BaseWidget<C> instance, String configJson) throws IOException {
final C config = om.readValue(configJson, instance.getConfigClass());
instance.setConfig(config);
}
可以使用通配符BaseWidget<? extends BaseConfig>
调用此方法就好了:
final BaseWidget<? extends BaseConfig> instance = new ConcreteWidget(new ConcreteConfig());
final BaseConfig config = instance.getConfig();
final String configJson = om.writeValueAsString(config);
parseSetConfig(instance, configJson);