【发布时间】:2022-02-28 15:26:44
【问题描述】:
考虑以下来自 JLS (§15.13.1) 的文章
如果满足以下所有条件,则以 Identifier 结尾的方法引用表达式是精确的:
- 如果方法引用表达式的格式为 ReferenceType ::[TypeArguments] Identifier,则 ReferenceType 不表示原始类型。
- 要搜索的类型只有一个名为 Identifier 的成员方法,该方法引用表达式所在的类或接口可以访问该方法。
- 此方法不是可变参数 (§8.4.1)。
- 如果此方法是通用方法(第 8.4.4 节),则方法引用表达式提供 类型参数。
考虑以下代码sn-p:
class Scratch {
public static void main(String[] args) {
Scratch.funct(new ImplementingClass()::<Functional1>hitIt);
}
public static void funct(Functional1 a){}
public static void funct(Functional2 a){}
}
interface Functional1 {<T> T hitIt();}
interface Functional2 {<T> T hitIt();}
class ImplementingClass{
public <T> T hitIt(){return null;}
}
显然 - 这满足了为准确引用方法而提到的所有条件。
不确定为什么在这种特殊情况下方法引用仍然不准确?我在条款中遗漏了什么吗?
解决办法:
根据@Sweeper @DidierL 和@Holger 的输入,我总结了以下内容:
- 两个功能接口都有 functionType
<T> () -> T - 方法引用
…::<Functional1>hitIt将T替换为Functional1,因此生成的函数签名为() -> Functional1,与<T> () -> T不匹配。
【问题讨论】:
-
是什么让您认为它不准确?
-
编译时 - 我收到错误消息 -:
reference to funct is ambiguous both method funct(Functional1) in Scratch and method funct(Functional2) in Scratch match -
我使用这个参考来了解编译器给出的不精确方法的症状-:blog.gilliard.lol/2017/10/23/…
-
请注意,像
<T> T hitIt()这样声明的方法确实是个坏主意,因为调用方不会进行编译时检查。它基本上说“我会猜测并返回调用者期望的任何东西,相信我”。几年前I faced an issue 在将应用程序从 Java 7 迁移到 8 时,使用类似的方法导致调用方调用了不同的、不相关的方法。而且我从来没有找到一种通用的方法来识别这种情况。 -
在您与@Sweeper 在他们(现已删除)的回答下进行的讨论之后,很明显,由于
Functional1/Functional2中的<T> T方法声明,这不应该编译,但是更改返回类型应该使它编译而不是编译。你能相应地更新你的问题吗?在问题本身中添加编译器错误也是值得的。
标签: java generics type-inference method-reference jls