Java 8流,为什么要编译第2部分......或者什么是方法参考,真的吗?

fge*_*fge 9 java java-8 functional-interface

好的,这个"系列"中的第一个问题就是这个问题.

现在,这是另一个案例:

Arrays.asList("hello", "world").stream().forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

这编译,并工作......

好的,在上一个问题中,使用了中的静态方法.

但现在这是不同的:System.out是一个static领域System,是的; 它也是一个PrintStream,并且PrintStream有一个println()恰好匹配a的签名的方法Consumer,并且a ConsumerforEach()期望的.

所以我试过这个......

public final class Main
{
    public static void main(final String... args)
    {
        Arrays.asList(23, 2389, 19).stream().forEach(new Main()::meh);
    }

    // Matches the signature of a Consumer<? super Integer>...
    public void meh(final Integer ignored)
    {
        System.out.println("meh");
    }
}
Run Code Online (Sandbox Code Playgroud)

它的工作原理!

这是一个完全不同的范围,因为我启动了一个新实例,并且可以在构造此实例后立即使用方法引用!

那么,一个方法参考真的是任何服从签名的方法吗?有什么限制?有没有人可以建立一个"@FunctionalInterface兼容"的方法,不能用于@FunctionalInterface

ass*_*ias 20

方法引用的语法在JLS#15.13中定义.特别是它可以是以下形式:

Primary :: [TypeArguments] Identifier

Primary除其他外,在哪里可以:

ClassInstanceCreationExpression

是的,你的语法是正确的.其他一些有趣的例子:

this::someInstanceMethod    // (...) -> this.someInstanceMethod(...)
"123"::equals               // (s) -> "123".equals(s)
(b ? "123" : "456")::equals // where b is a boolean
array[1]::length            // (String[] array) -> array[1].length()
String[]::new               // i -> new String[i]
a.b()::c                    // (...) -> a.b().c(...)
Run Code Online (Sandbox Code Playgroud)

顺便说一下,既然你提到了静态方法,那么有趣的是你不能从实例创建一个静态方法引用:

class Static { static void m() {} }
Static s = new Static();

s.m(); //compiles
someStream.forEach(s::m); //does not compile
someStream.forEach(Static::m); //that's ok
Run Code Online (Sandbox Code Playgroud)