现在,这是另一种情况:
Arrays.asList("hello", "world").stream().forEach(System.out::println);
这样可以编译并运行…
好的,在最后一个问题中,使用了来自 类的 静态方法。
但是现在不同了:System.out是的static字段System,是;在这种情况下,它也是a PrintStream,并且a PrintStream具有println()碰巧匹配a的签名的方法Consumer,而a Consumer是forEach()期望的方法。
System.out
static
System
PrintStream
println()
Consumer
forEach()
所以我尝试了这个
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"); } }
而且有效!
这是一个完全不同的范围,因为我启动了一个新实例,并且可以在构造该实例之后立即使用方法引用!
那么,方法引用真的是 任何 遵循签名的方法吗?有什么限制?在任何情况下都可以构建“ @FunctionalInterface兼容”方法,而该 方法不能 在@FunctionalInterface?中使用?
@FunctionalInterface
方法引用的语法在JLS#15.13中定义。特别是可以采用以下形式:
Primary :: [TypeArguments] Identifier
Primary除其他事项外,哪里可以是:
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(...)
顺便说一句,由于您提到了静态方法,因此有趣的是您不能从实例创建静态方法引用:
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