当前位置: 首页 > 知识库问答 >
问题:

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

刘选
2023-03-14

为什么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);
    }
}

共有1个答案

饶德元
2023-03-14

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

如果使用不兼容的界限,例如integerlong,则尝试推断公共下界可能会失败。当我们使用上界时,总是有可能找到一些共同的上界,在本例中是list<?扩展number>。但是列表<没有共同的下界?超级整数>列表<?超长>。发生这种冲突时唯一安全的选择是返回list<?extends Object>,与列表<?>同义,意思是“未知类型的列表”。

现在,可以说,只有当实际存在冲突的界限时,我们才可以诉诸于此,与我的问题中的情况相反。但也许我们决定采取简单的方法,不假设有一个公共的下界,除非明确指定。

 类似资料:
  • 有没有办法告诉Java不要试图从使用基元类型的方法引用中推断类型? 这是我写的一个方法,原因现在无关紧要: 现在,如果您将方法引用传递给返回原始类型的“isEquals”,该怎么办? 这一切都很好,但Java也会接受这种奇怪的用法: 这是因为编译器将推断类型参数T为"

  • 问题内容: 所以我有一张地图: 我会像这样添加元素: 我有如下通用方法: 现在,这段代码可以很好地工作,并且没有编译器问题: 但是,当我尝试这样做时: 编译器向我显示以下警告:类型安全:通用方法verifyType(String,Class)的未经检查的调用verifyType(String,Class) 这让我感到困惑…请帮助… 问题答案: 更改: 至 通过仅将类型声明为“ Class”,就失去

  • 问题内容: 我了解编译器使用目标类型来确定使通用方法调用适用的类型参数。例如,在以下语句中: 其中的签名中具有类型参数 在这种情况下,推断出的类型参数是。 现在考虑以下几点: 在这种情况下,推断的类型是什么?是吗 还是因为通配符告诉编译器任何类型都是可能的? 问题答案: 通配符的每种用法都有与之关联的不同类型。(通常,JLS将此称为“新鲜类型”。)例如,这就是这样的编译器错误的工作方式: 因为在这

  • 我知道编译器使用目标类型来确定使泛型方法调用适用的类型参数。例如,在以下声明中: 其中

  • 我为协变返回类型的继承创建了一个小示例。基本上有三种不同的类别: 主应用程序: BaseManager: 鸟经理: 当我重写方法以返回时,为什么我需要将类型转换为? 我使用过的重写方法在返回类型上会有所不同吗?作为参考。 编辑: 我有不同的子模型,它们都继承自。所有模型都允许存在一次。我尝试将这些模型添加到列表中,而不是对每个模型使用单例。使用,我想得到实际的模型。也许我得考虑太多了。

  • 问题内容: 考虑以下代码: 排序调用给出错误: 绑定不匹配:类型为Collections的通用方法sort(List )不适用于参数(ArrayList >)。推断的类型MyItem 不是有效替代边界参数<T扩展Comparable <?超级T>> 为什么会这样呢? 如果实施该工具,那为什么不能替代呢? 抱歉,是否有人提出这个问题,但我觉得这个问题有些具体。 问题答案: 实际上,对该错误的更详细说