来自 class 类型的实例方法的方法引用 vs 来自实例的实例方法的方法引用
Method reference to instance method from class type vs Method reference to instance method from instance
从实例中引用实例方法的方法
// compile successfully, out is instance, println is instance method
Consumer<String> c = System.out::println;
方法引用来自 class 类型的实例方法
// compile fail, PrintStream is class type, println is instance method
Consumer<String> c = PrintStream::println;
为什么 Consumer<String> c = PrintStream::println
失败了?
但是!
BiConsumer<PrintStream, String> c = PrintStream::println; // compiles!
对 class 的方法引用具有实例的隐式第一个参数。这类似于 Method
的 invoke()
方法的第一个参数是实例。
答案就在你的问题中。 PrintStream.println(String)
是一个实例方法,意味着调用该方法需要一个实例。
有了这个
Consumer<String> c = PrintStream::println
Java在调用c.accept(String)
时,不知道去哪里找PrintStream
实例调用println()
。如果 println
是 PrintStream
中的 static
,代码将编译。
这与
不同
Consumer<String> c = System.out::println
已经指定了调用println
的实例(实例为System.out
)。
有些情况下不需要显式指定要调用方法引用的实例,例如(为简单起见借用对象方法)
Consumer<String> c = String::notify; //notify is an instance method
之所以编译是因为 Java 可以使用传递给 Consumer.accept
的参数作为方法的目标,因此 String::notify
可以用于该目的。但事情并没有这么简单(例如,notify
是无效的),所以通过 docs/spec 了解如何解析方法引用很重要(这是一个很好的起点:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html).
因为无法从 static
上下文中引用 non-static
方法。
您可以在System.java
中查看
public static final PrintStream out = null;
out
是 static
,这就是它正在编译的原因。
同时,为了访问 PrintStream
的 println
,您必须先创建 PrintStream
的实例,然后调用 println
.
PrintStream printStream = new PrintStream("File");
Consumer<String> c = printStream::println;
从实例中引用实例方法的方法
// compile successfully, out is instance, println is instance method
Consumer<String> c = System.out::println;
方法引用来自 class 类型的实例方法
// compile fail, PrintStream is class type, println is instance method
Consumer<String> c = PrintStream::println;
为什么 Consumer<String> c = PrintStream::println
失败了?
但是!
BiConsumer<PrintStream, String> c = PrintStream::println; // compiles!
对 class 的方法引用具有实例的隐式第一个参数。这类似于 Method
的 invoke()
方法的第一个参数是实例。
答案就在你的问题中。 PrintStream.println(String)
是一个实例方法,意味着调用该方法需要一个实例。
有了这个
Consumer<String> c = PrintStream::println
Java在调用c.accept(String)
时,不知道去哪里找PrintStream
实例调用println()
。如果 println
是 PrintStream
中的 static
,代码将编译。
这与
不同Consumer<String> c = System.out::println
已经指定了调用println
的实例(实例为System.out
)。
有些情况下不需要显式指定要调用方法引用的实例,例如(为简单起见借用对象方法)
Consumer<String> c = String::notify; //notify is an instance method
之所以编译是因为 Java 可以使用传递给 Consumer.accept
的参数作为方法的目标,因此 String::notify
可以用于该目的。但事情并没有这么简单(例如,notify
是无效的),所以通过 docs/spec 了解如何解析方法引用很重要(这是一个很好的起点:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html).
因为无法从 static
上下文中引用 non-static
方法。
您可以在System.java
public static final PrintStream out = null;
out
是 static
,这就是它正在编译的原因。
同时,为了访问 PrintStream
的 println
,您必须先创建 PrintStream
的实例,然后调用 println
.
PrintStream printStream = new PrintStream("File");
Consumer<String> c = printStream::println;