首页 > 解决方案 > 可作为方法参考运行

问题描述

为什么这段代码不能编译?无法完全掌握细微差别的 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 !!

    }
}

标签: javalambdajava-8method-reference

解决方案


这里有一些误解,其他答案只提供最终结果。所以这里有一个真实的解释。

在 java 中,有 lambda ( () -> something) 和方法引用 ( Class::method)。它们基本上是一样的,只是语法不同(更短)。如果您愿意,您可以混合使用 lambda 和方法引用(lambda 中的 lambda,lambda 中的方法引用)。只要一切都是正确的类型,你就可以了。

类型的System.out::println方法引用也是如此Consumer<String>,原因作为参数,并返回- 那是. (也有不带参数的,在这种情况下它是 a )System.out.println()StringvoidConsumer<String>System.out.println()Runnable

Runnable有点不同,因为它不接收任何参数或返回值。示例可能是List::clear.

至于为什么您的代码是编译错误:

将 a 声明Runnable为 lambda 时,您必须不接收任何参数并返回void。这个 lambda:Runnable r1 = () -> System.out::println;不符合条件,因为它不接收任何参数 ( () ->),但它的表达式确实返回类型 - Consumer<String>(或Runnable再次),而不是void. Runnable如果您设法不返回任何内容,这可能是有效的,例如

Runnable r1 = () ->  {
  Consumer<String> str1 = System.out::println; // either this
  Runnable str2 = System.out::println; // or this
  return; // return type - void
}

但这有点没有意义。

所以你可以清楚地看到,这() -> System.out::println()实际上是一个提供Runnableor的 lambda Consumer<String>,所以它的类型应该是

Supplier<Runnable> s = () -> System.out::println; // either this
Supplier<Consumer<String>> s = () -> System.out::println; // or this

要直接使用它,你只需要放弃Supplier<>

Runnable s = System.out::println; // either this
Consumer<String> s = System.out::println; // or this

不如你解释一下你想做什么,我们会帮你的。


推荐阅读