为什么有时不能仅引用非静态方法?

时间:2018-10-16 10:49:17

标签: java generics static

我遇到了一个相当奇怪的编译器行为:可以从静态上下文中引用非静态方法,但并非总是如此。 我的理解是

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是合理的。

1 个答案:

答案 0 :(得分:3)

这似乎是编译器错误报告不佳的情况。使用我的编译器(Eclipse),我得到了错误:

  

Child类型未定义在此处适用的doSomething(Parent,String)

确实没有,因为实例方法具有隐式接收方参数(this),对于Child::doSomething而言,其隐含类型为Child,因此BiConsumer<Parent, String>不是兼容的目标类型。

您可以使用对Parent的{​​{1}}版本的引用:

doSomething