我遇到了一个相当奇怪的编译器行为:可以从静态上下文中引用非静态方法,但并非总是如此。 我的理解是
void method() {}
和
void static method(ThisClassName c) {}
在JVM中应该具有相同的签名,因此它们的引用应具有相同的行为,但是显然我错了。
这是我的例子:
父母:
package com.example;
abstract class Parent<S> {
abstract void doSomething(final S s);
}
孩子:
package com.example;
import java.util.function.BiConsumer;
class Child extends Parent<String> {
// This line compiles OK
private static BiConsumer<Child, String> consumer1 = Child::doSomething;
// Compiler error: "Non-static method cannot be referenced from a static context."
private static BiConsumer<Parent, String> consumer2 = Child::doSomething;
// This line compiles OK
private static BiConsumer<Parent, String> consumer3 = Child::doSomethingElse;
@Override
void doSomething(final String s) {
// do something
}
static void doSomethingElse(final Parent<String> c, final String s) {
// do something else
}
}
这里的问题是由于编译器错误而无法设置consumer2。
我是怎么发现的:我需要通过
Map<String, BiConsumer<Parent, ?>>
周围,并且地图本身仅创建一次(在启动时),因此将其设为静态final是合理的。
答案 0 :(得分:3)
这似乎是编译器错误报告不佳的情况。使用我的编译器(Eclipse),我得到了错误:
Child类型未定义在此处适用的doSomething(Parent,String)
确实没有,因为实例方法具有隐式接收方参数(this
),对于Child::doSomething
而言,其隐含类型为Child
,因此BiConsumer<Parent, String>
不是兼容的目标类型。
您可以使用对Parent
的{{1}}版本的引用:
doSomething