3

I have a class which has a self referential generic parameter and a parameter which is of the same super class. The static function has identical bounds as the class.

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) {
    }
}

This gives the following error.

Bound mismatch: The generic method foo(S_T) of type Bar<T,C> is not applicable for the arguments (C). The inferred type C is not a valid substitute for the bounded parameter <S_T extends Bar<S_T,S_C>>

I can't figure out why C can't be passed in to foo() since C is Bar<C,?> and the wildcard is a Bar because of the second parameter in the declaration says it extends Bar.

I know this is probably a bad idea and produces code which is hard to understand but I really wanna know why this doesn't compile.

4

2 回答 2

2

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

Java 没有对?声明中的通配符执行任何智能推理,Bar以推断它在逻辑上是由Bar< ?, ? >(也不是该边界中的?s 本身是有界的,等等)。一旦你把?它自己放进去,这就是 Java 所知道的一切。尽管没有什么能阻止您在 的声明中将通配符放在通配符上Bar,但即使这样也无助于 Java;Java 永远不会假设两个单独?的 s 引用相同的类型,即使更深入的分析表明它们必须如此。换句话说,即使使用以下代码,编译错误仍然存​​在:

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) {
    }
}
于 2012-06-12T00:06:34.597 回答
0

我不是泛型的专家,但我认为问题在于您将 foo() 的类型声明为

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

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

在第一个上下文中S_T有 type T,在第二个上下文中它有 type C。但是TandC被声明为Bar<T,?>and Bar<C,?>,它们是静态不兼容的类型。我猜编译器会foo()在第一次调用中计算出类型,然后正确假设类型必须始终保持不变,但事实并非如此。

于 2012-06-11T18:39:22.337 回答