【发布时间】:2018-05-03 07:24:43
【问题描述】:
我有以下课程
接口 1
package test;
public interface TODO {
boolean test();
}
界面2
package test;
@FunctionalInterface
public interface FuncN {
State zip(State ...states);
}
1 级
package test;
public class Test {
public static Test define(FuncN zipperFunc,TODO... tasks) {
return null;
}
public static Test define(TODO... tasks) {
return null;
}
}
2 级
封装测试;
public class State {
public static State mergeStates(State ...states) {
return null;
}
}
主类
package test;
public class Main {
public static void main(String[] args) {
Test.define(State::mergeStates,()->true);
}
}
主类没有编译,抛出错误
对定义的引用不明确 Test.define(State::mergeStates,()->true); ^ Test 中的方法 define(FuncN,TODO...) 和 Test 匹配中的方法 define(TODO...)
下面的类确实编译:
package test;
public class Main {
public static void main(String[] args) {
Test.define(states->State.mergeStates(states),()->true);
}
}
但是我没有看到任何歧义。 FuncN 和 TODO 的签名完全不同,我认为编译器不应该将它们误认为是另一个。
如果我错了,请纠正我。
附注使用 eclipse 无法重现错误,因此我建议创建一个文件夹 test 在其中创建所有 java 文件并运行 javac test/Main.java
【问题讨论】:
-
我无法复制。
Test.define(State::mergeStates,()->true);为我通过编译。 -
我的 jvm 规格如下: java 版本 "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0_171-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.171- b11,混合模式)javac 1.8.0_171。它不会在 Eclipse 中引发任何错误,我建议创建一个文件夹 test 将所有文件放入其中,然后运行 javac test/Main.java 这就是引发错误的方式。
-
由于
mergeState是一个varargs方法,State::mergeStates是一个不精确的方法引用,它需要目标类型得到完全解析,但是在知道将调用哪个define方法之前,不知道目标类型,但是必须在不考虑State::mergeStates参数的情况下做出此决定,其功能签名未知。虽然可以排除一种变体,例如通过尝试,规范不包括这样的测试(故意不进一步增加复杂性)。 -
所以当你将目标方法设为非varargs,即
public class State { public static State mergeStates(State[] states) { return null; } },错误就会消失。 -
@Holger 我不知道你为什么不回答这个问题,这又是 我们需要解析方法才能找到目标类型的情况,但我们需要知道目标类型以解析方法。我发誓每次遇到这种情况我都必须去重新阅读我的笔记
标签: java-8 javac method-reference