为什么这种类型不能替代类型参数?

时间:2011-08-11 21:15:36

标签: java generics

我正在尝试使用泛型来支持委托对象(装饰器,包装器)的可配置结构。我想构建一个实现目标接口和通用委托接口的委托链。

我有这个大纲:

class Test {
    static interface Delegator<T> {}

    static class DelegatorChain<T extends Delegator<T>> {}

    static interface Foo {}

    static class FooDelegator implements Delegator<Foo>, Foo {}

    public static void main(String[] args) {
        DelegatorChain<FooDelegator> chain = new DelegatorChain<FooDelegator>();
    }
}

但是,在尝试实例化chain变量时,编译器会抱怨:

  

绑定不匹配:Test.FooDelegator类型不能替代<T extends Test.Delegator<T>>类型的有界参数Test.DelegatorChain<T>

我承认泛型对我来说就像magic,但我可以以某种方式承认FooDelegator不是扩展 Delegator&lt; Foo&gt;的Foo,它只是实现了两个接口。

鉴于我想要完成的事情很清楚,我能做些什么吗?用于修复它的泛型,还是我最好忘记它?

3 个答案:

答案 0 :(得分:9)

根据您的定义,Delegator本身就是一个Delegator(例如Comparable),但似乎意图是Delegator是超类的Delegator。幸运的是,泛型有一种表达方式:

static class DelegatorChain<T extends Delegator<? super T>> {}

这表示“Delagator类型必须是T的超类”。通过此更改,原始代码的其余部分将编译:

static interface Delegator<T> {}
static class DelegatorChain<T extends Delegator<? super T>> {}
static interface Foo {}
static class FooDelegator implements Delegator<Foo>, Foo {}

public static void main(String[] args) {
    DelegatorChain<FooDelegator> chain = new DelegatorChain<FooDelegator>();
}

此外,无论何时使用通用超级绑定,您的代码看起来都很酷:)



注意:以下内容最初是问题中的“第一选项” 还有另一种方法可以让您的代码进行编译,但它是次要的,因为它失去了Delegator类型与委托代理之间的连接:

// Not recommended, but will allow compile:
static class FooDelegator implements Delegator<FooDelegator>, Foo {} 
// However, this also compiles :(
static class FooDelegator implements Delegator<FooDelegator>, Bar {} 

答案 1 :(得分:3)

看起来这就是你要做的事。

static interface Delegator<T> {
    }

    static class DelegatorChain<T extends Delegator<C>, C> {
    }

    static interface Foo {
    }

    static class FooDelegator implements Delegator<Foo>, Foo {
    }

    public static void main(String[] args) {
        DelegatorChain<FooDelegator, Foo> chain = new DelegatorChain<FooDelegator, Foo>();
    }

您的初始示例无法编译,因为类型不正确。 DelegatorChain中的Generic类型是“FooDelegator”,但Delegator中所需的泛型类型是“Foo”。您需要我在答案中提供的额外泛型类型参数,以使其按预期工作。

您也可以将约束完全保留在DelegatorChain上,即DelegatorChain。

答案 2 :(得分:0)

如果FooDelegator implements Delegator<FooDelegator>Foo implements Delegator<Foo>,应该做什么。因为这是DelegatorChain所要求的:T implements Delegator<T>

第三种选择,也应该有效:

DelegatorChain<T extends Delegator<F>, F> chain; ...