Java 8方法引用特定类型的任意对象的实例方法

dab*_*bai 7 java functional-programming java-8

为什么以下不起作用?

import java.util.function.Function;

public class MethodRefTest {
   public String passMeAround( String input ) {
      return input + " been passed to me";
   }

   public Function<String, String> testReferences() {
      final Function<String, String> f1 = MethodRefTest::passMeAround;
      return f1;
   }

   public static void main( String[] args ) {
      new MethodRefTest()
            .testReferences()
            .apply( "foo" );
   }
}
Run Code Online (Sandbox Code Playgroud)

Javac告诉我:

MethodRefTest.java:14: error: invalid method reference
      final Function<String, String> f1 = MethodRefTest::passMeAround;
                                          ^
  non-static method passMeAround(String) cannot be referenced from a static context
1 error
Run Code Online (Sandbox Code Playgroud)

我不明白为什么上下文是静态的.我读过这个,但它似乎没有回答手头的问题.

编辑

同样根据oracle,"可以通过引用特定类型的任意对象的实例方法 "ContainingType::methodName

编辑2

@ marko-topolnik帮我理解了我的错误. Function<String, String> f1 = MethodRefTest::passMeAround; 指静态方法String MethodRefTest.passMeAround(String)

BiFunction<MethodRefTest, String, String> f1 = MethodRefTest::passMeAround;
Run Code Online (Sandbox Code Playgroud)

另一方面,指的any instance是apply子句中传递的实例方法.

BiFunction<MethodRefTest, String, String> f2 = MethodRefTest::passMeAround;
//call instance method
f2.apply(new MethodRefTest(), "some string");
Run Code Online (Sandbox Code Playgroud)

Mar*_*nik 15

因为你称之为

MethodRefTest::passMeAround
Run Code Online (Sandbox Code Playgroud)

你应该把它称为

this::passMeAround
Run Code Online (Sandbox Code Playgroud)

提供用于上下文的实例.

查看当前代码的另一种方法是说这MethodRefTest::passMeAround是一个BiFunction<MethodRefTest, String, String>并且此lambda形状与目标站点不匹配.所以,或者,你可能已经写过了

public BiFunction<MethodRefTest, String, String> testReferences() {
  return MethodRefTest::passMeAround;
}
Run Code Online (Sandbox Code Playgroud)

并在主要方法

final MethodRefTest t = new MethodRefTest();
t.testReferences().apply( t, "foo" );
Run Code Online (Sandbox Code Playgroud)

你读过的材料可能不够有用,所以让我扩展一下.同

this::passMeAround
Run Code Online (Sandbox Code Playgroud)

你得到一个lambda对象,它从创建它的上下文中捕获this实例,但是

MethodRefTest::passMeAround
Run Code Online (Sandbox Code Playgroud)

你会得到一个"纯粹的"非捕获lambda,它表示在某个实例上调用指定方法,并带有一些字符串参数,所以当你使用apply它时,你需要传入两者.