具有下界类型的Java类型推断

具有下界类型的Java类型推断,java,generics,type-inference,bounded-wildcard,Java,Generics,Type Inference,Bounded Wildcard,为什么Java可以推断出多个上限类型的共同祖先,而不能推断出下限类型的共同祖先 更具体地说,考虑下面的例子: static class Test { static <T> T pick(T one, T two) { return two; } static void testUpperBound() { List<? extends Integer> extendsInteger = new ArrayList

为什么Java可以推断出多个上限类型的共同祖先,而不能推断出下限类型的共同祖先

更具体地说,考虑下面的例子:

static class Test {

    static <T> T pick(T one, T two) {
        return two;
    }

    static void testUpperBound() {
        List<? extends Integer> extendsInteger = new ArrayList<>();

        // List<? extends Integer> is treated as a subclass of List<? extends Number>
        List<? extends Number> extendsNumber = extendsInteger;

        // List<? extends Number> is inferred as the common superclass
        extendsNumber = pick(extendsInteger, extendsNumber);
    }

    static void testLowerBound() {
        List<? super Number> superNumber = new ArrayList<>();

        // List<? super Number> is treated as a subclass of List<? super Integer>
        List<? super Integer> superInteger = superNumber;

        // The inferred common type should be List<? super Integer>,
        // but instead we get a compile error:
        superInteger = pick(superNumber, superInteger);

        // It only compiles with an explicit type argument:
        superInteger = Test.<List<? super Integer>>pick(superNumber, superInteger);
    }
}
静态类测试{
静态T拾取(T 1,T 2){
返回两个;
}
静态void testUpperBound(){

List我正在使用1.8.0_25,我得到了编译错误。 然而,错误不在于对pick的调用不正确,而在于要将结果放入的变量。 重复你的例子:

static void testLowerBound() {
    List<? super Number> superNumber = new ArrayList<>();
    List<? super Integer> superInteger = superNumber;

    // this gets the error
    superInteger = pick(superNumber, superInteger);
    // this doesn't
    pick(superNumber, superInteger);

    // what's happening behind is
    List<? extends Object> behind = pick(superNumber, superInteger);
    superInteger = behind;
    // that last line gets the same compilation error
}
static void testLowerBound(){

List我想我可以解释为什么Java区分下限类型和上限类型


如果使用不兼容的边界,例如
Integer
Long
,尝试推断公共下界可能会失败。当我们使用上界时,总是可以找到一些公共上界,在这种情况下
列表您的测试使用1.8.025为我编译,没有显式类型参数。@Alex我使用的是1.7.Maybe它已经被修复了。我看不出你的推理。就像我们用
扩展
将绑定转移到最近的公共超类(
数字
),我们应该用
超级
将它转移到最近的公共子类(
整数
)。