为什么这段代码不能编译?无法完全掌握java方法引用的细微差别:(
public class TestClass {
static void println() {}
public static void main(String[] args) {
Runnable r1 = () -> System.out::println; // compilation error
Runnable r2 = () -> TestClass::println; // compilation error
Runnable r2 = () -> System.out.println("Hello World"); // This is fine !!
}
}
5条答案
按热度按时间5q4ezhmt1#
它应该是一个“直接”的方法引用,而不是一个方法引用所代表的东西的提供者。
比较
具有
vngu2lb82#
在本例中,system.out.println是一个使用者(它接受一个字符串并用它做一些事情)
或无:
g6baxovj3#
方法引用不是这样工作的。你这样使用它们:
zz2j4svz4#
因为你需要这样写:
在这里您可以阅读更多关于方法引用的信息https://docs.oracle.com/javase/tutorial/java/javaoo/methodreferences.html
64jmpszr5#
这里有一点误解,其他答案只能提供最终结果。所以这里有一个真正的解释。
在java中,有lambda(
() -> something
),和方法引用(Class::method
). 它们基本上是一样的,只是语法不同。如果愿意,可以混合lambda和方法引用(lambda中的lambda,lambda中的方法引用)。只要一切都是正确的类型,你就没事。所以呢
System.out::println
是类型的方法引用Consumer<String>
,原因System.out.println()
拿String
作为参数,并返回void
-那是Consumer<String>
. (还有System.out.println()
这不需要争论,如果那样的话,那将是一场战争Runnable
)Runnable
有点不同,因为它不接收任何参数或返回值。例如List::clear
.至于为什么你的代码是编译错误:
在声明
Runnable
作为lambda,您必须不接收任何参数并返回void
. 这个lambda:Runnable r1 = () -> System.out::println;
不符合条件,因为它不接收任何参数(() ->
),但它的表达式确实返回类型-Consumer<String>
(或Runnable
再说一遍),不是void
. 它可能是一个有效的Runnable
如果你什么也没归还,比如但那是没有意义的。
所以你可以清楚地看到
() -> System.out::println()
实际上是一个供应Runnable
或者Consumer<String>
,所以它的类型应该是要直接使用它,你只需要抛弃
Supplier<>
```Runnable s = System.out::println; // either this
Consumer s = System.out::println; // or this