Java嵌套自引用泛型

时间:2012-06-11 18:25:44

标签: java generics

我有一个具有自引用泛型参数的类和一个具有相同超类的参数。静态函数与类具有相同的边界。

public class Bar<T extends Bar<T, C>, C extends Bar<C, ?>> {

    Bar() {
        foo((T) null);
        foo((C) null);//compile error
    }

    static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ?>> void foo(S_T t) {
    }
}

这会产生以下错误。

  

绑定不匹配:Bar&lt; T,C&gt;类型的通用方法foo(S_T)。不是   适用于论点(C)。推断的类型C无效   替代有界参数&lt; S_T extends Bar&lt; S_T,S_C&gt;&gt;

我无法弄清楚为什么C无法传递给foo(),因为CBar<C,?>且通配符为Bar,因为声明中的第二个参数表示它扩展了Bar。

我知道这可能是一个坏主意并产生难以理解的代码,但我真的想知道为什么这不能编译。

2 个答案:

答案 0 :(得分:2)

简短的回答是Java类型推断实际上非常蹩脚。

Java未在?声明中对通配符Bar执行任何智能推断,以推断它在Bar< ?, ? >的逻辑上受限(也不是? s在那个界限本身是有界的,等等)。一旦你自己放了?,这就是所有Java都知道的。虽然没有什么可以阻止你在Bar的声明中将那个绑定放在通配符上,但是这对Java没有帮助; Java不会假设两个单独的?引用相同的类型,即使更深入的分析意味着必须这样做。换句话说,即使使用以下代码,编译错误仍然存​​在:

public class Bar<T extends Bar<T, C>, C extends Bar<C, ? extends Bar<?, ? extends Bar<?, ?>>>> {

    Bar() {
        foo((T) null);
        foo((C) null);//compile error
    }

    static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ? extends Bar<?, ? extends Bar<?, ?>>>> void foo(S_T t) {
    }
}

答案 1 :(得分:0)

我不是泛型的破解,但我认为问题是你声明foo()的类型是

<S_T extends Bar<S_T,S_C> > void foo(S_T)

然后在两个不同的上下文中调用它,这些上下文需要foo()的不同静态类型。

在第一个上下文中,S_T具有类型T,而在第二个上下文中,它具有类型C。但TC被声明为Bar<T,?>Bar<C,?>,它们是静态不兼容的类型。 我猜想编译器会在第一次调用中找出foo()的类型,然后正确地假设,类型必须始终保持相同,而不是。