3

情况:我正在制作一个配置库,带有一个表示数据的 Config 接口和一个像这样的 Parser 接口:

public interface Parser<C extends D, D extends Config> {
    C parse(File f);
    void parse(File f, D destination);
}

解析器必须能够将数据解析为新的配置对象 (C) 或现有的配置对象 (D)。C 扩展了 D,因为我们可以手动创建 C 并将数据解析到其中是合乎逻辑的。当然 D 扩展了 Config 因为我们解析配置。

假设我们有一个实现 Config 的类 MyConfig(但它也可以是一个通用的“T extends Config”),并且我们想要一个可以创建和解析它的 Parser。让我们遵循 PECS 规则:

  • 我们的解析器可以解析 MyConfig,但也可能是它的超类型 => 我应该使用“?super MyConfig”
  • 我们的解析器可以生成 MyConfig,但也许它实际上会生成一个子类型 => 我应该使用 "? extends MyConfig"

因此我最终得到了这个:

Parser<? extends MyConfig, ? super MyConfig> parser;

但是,虽然 IntelliJ 没有抱怨任何事情,但编译(javac 1.8.0_131)失败并出现以下错误:

类型参数?extends package.MyConfig 不在类型变量 C 的范围内

这很奇怪,因为“MyConfig 的某个子类型”显然是“MyConfig 的某个超类型”的子类型,对吧?

仅当同时使用两个通配符时才会出现此问题。此外,使用另一种泛型类型而不是上限有效:

// All these are fine
Parser<? extends MyConfig, MyConfig>
Parser<MyConfig, ? super MyConfig>
<J extends MyConfig> void test(Parser<J, ? super MyConfig> parser)

我在这里想念什么?我可以用我的生产者-消费者解析器做什么?

编辑:我发现一些更令人困惑的事情:使用 Config 的子接口而不是子类可以工作,即编译得非常好:

interface SpecialConfig extends Config {}
Parser<? extends SpecialConfig, ? super SpecialConfig> specialParser;
4

0 回答 0