Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么非静态方法有时不能被引用?_Java_Generics_Static - Fatal编程技术网

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

Java 为什么非静态方法有时不能被引用?,java,generics,static,Java,Generics,Static,我遇到了一个相当奇怪的编译器行为:可以从静态上下文引用非静态方法,但并不总是这样。 我的理解是 void method() {} 及 JVM中应该有相同的签名,因此它们的引用应该表现相同,但显然我错了 以下是我的例子: 家长: package com.example; abstract class Parent<S> { abstract void doSomething(final S s); } package.com.example; 抽象类父类{ 抽象无效剂量测

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

void method() {}

JVM中应该有相同的签名,因此它们的引用应该表现相同,但显然我错了

以下是我的例子:

家长:

package com.example;

abstract class Parent<S> {
    abstract void doSomething(final S s);
}
package.com.example;
抽象类父类{
抽象无效剂量测定法(最终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
    }

}
package.com.example;
导入java.util.function.BiConsumer;
类子级扩展父级{
//这行代码编译正常
私有静态双消费者消费者1=Child::doSomething;
//编译器错误:“无法从静态上下文引用非静态方法。”
私有静态双消费者消费者2=Child::doSomething;
//这行代码编译正常
私有静态双消费者消费者3=Child::doSomethingElse;
@凌驾
无效剂量测定(最终字符串s){
//做点什么
}
静态void doSomethingElse(最终父级c,最终字符串s){
//做点别的
}
}
这里的问题是,由于编译器错误,无法设置consumer2

我是如何认识到这一点的:我需要通过考试

Map<String, BiConsumer<Parent, ?>>
Map

而映射本身只构建了一次(在启动时),因此将其设为静态最终版本是有意义的。

这看起来像是一个编译器错误报告不佳的案例。使用我的编译器(Eclipse),我反而得到了错误:

类型Child未定义适用于此处的doSomething(父项、字符串)

实际上它没有,因为实例方法有一个隐式接收器参数(
this
),它对于
Child::doSomething
具有类型
Child
,所以
BiConsumer
不是兼容的目标类型

您可以使用对
父级
版本的
doSomething
的引用:

private static BiConsumer<Parent, String> consumer2 = Parent::doSomething;
private static双消费者2=Parent::doSomething;

“…在JVM中应该具有相同的签名,因此它们的引用应该具有相同的行为…”您会怎么想?这一点都不正确。请阅读。@AlexeyNezhdanov-不,他们不正确。一个是不带参数的实例方法(以及隐式
this
参数),另一个是带显式
AClass
参数的静态方法。这些是不同的签名。实例方法上的隐式
this
不仅仅是
静态
上的前导类类型参数。(概念上有些相似,但仅此而已。)@AlexeyNezhdanov-怎么样?:-)“两个方法或构造函数,M和N,如果它们具有相同的名称、相同的类型参数(如果有)(§8.4.4),并且在将N的形式参数类型调整为M的类型参数后,具有相同的形式参数类型,则具有相同的签名。”
不是形式参数。这是一个接收方参数(),它显然不是一个正式参数。@T.J.Crowder谢谢!
private static BiConsumer<Parent, String> consumer2 = Parent::doSomething;