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

为什么这个Java泛型方法调用在分离时只有一个方法有效时是不明确的?

方弘
2023-03-14

我试图理解为什么编译器无法解析bar方法调用。我希望bar(Xyz::new)总是选择bar(suppliver),因为bar(T extends Xyz)由于Xyz的上限而永远不能匹配。

public <T extends Xyz> void foo(T s) {}
public <T extends Xyz> void bar(T s) {}
public <T extends Xyz> void bar(Supplier<T> s) {}

public void example() {
    foo(Xyz::new); // not valid (does not extend Xyz)

    bar((Supplier<Xyz>) Xyz::new); // valid (explicitly a Supplier)
    bar(Xyz::new); // ambiguous - but only one method is valid?
}

public static class Xyz {}

如果bar(T)不适用,即使单独使用(如foo(T))所示),那么唯一的选择肯定是bar(suppliver),这将是一个非歧义的重载。

为什么bar调用不明确,尤其是当foobar(T)调用本身不是有效的解析时?

上面代码的可运行示例:https://www.jdoodle.com/ia/kqp

共有1个答案

李俭
2023-03-14

您说得对,一个更聪明的编译器应该能够明确地解决这个问题。

Java解析方法调用的方式很复杂。它是由JLS定义的,我编写了7500字,纯粹是为了确定如何解析一个方法。粘贴到文本编辑器中,它有15页。

一般做法是:

    null
 类似资料:
  • 如果方法定义为: 第一个T加什么?因为它与以下内容基本相同:

  • 问题内容: 给定一些类,这两个方法声明是否等效? 和 问题答案: 对于呼叫者:是的,它们是等效的。 对于方法中的代码:否。 不同之处在于,在第一个示例的代码中,您可以使用类型T(例如,保存由创建的对象),而在第二个示例中,您不能使用类型T。

  • 这怎么可能呢?为什么添加另一个参数会导致方法解析不明确?为什么在第一个例子中它可以区分供应商和对象,而在第二个例子中却不能? 编辑:这使用的是1.8.0_121。这是完整的错误消息:

  • 问题内容: 我注意到使用泛型和lambda重载方法的行为很奇怪。这个课程效果很好: 没有模棱两可的方法调用。但是,将其更改为此将使第二个调用不明确: 怎么会这样?为什么添加另一个参数会导致方法解析不明确?为什么在第一个示例中却能分辨出Supplier和Object之间的区别,而在第二个示例中却不能呢? 编辑:这是使用1.8.0_121。这是完整的错误消息: 问题答案: 如果我对JSE for Ja

  • 运行此代码时,Clang(3.9.1)和GCC(7,快照)将“1”、“2”打印到控制台。 但是,MSVC未能编译此代码: source_file.cpp(15):错误C2668:字典::集:对重载函数的模糊调用 source_file.cpp(9):注意:可能是“无效字典::集(int64_t)” source_file.cpp(8):注意:或'无效字典::集(const char*)' 源文件。

  • 主课 工具类 考试班 输出: 我试图嘲笑util无效的方法调用与do没什么,但不工作。有人能帮我解决吗?我在我们的应用程序中遇到了类似的功能。