2016-03-10 114 views
5

我想在我的代码中使用Java 8方法引用。有四种可用的方法参考。Java 8:方法参考绑定接收器和UnBound接收器之间的区别

  1. 静态方法参考。
  2. 实例方法(绑定接收器)。
  3. 实例方法(UnBound receiver)。
  4. 构造函数的参考。

随着Static method referenceConstructor reference我没有问题,但Instance Method (Bound receiver)Instance Method (UnBound receiver)真的搞糊涂了。在Bound接收机中,我们使用一个对象引用变量调用的方法等:

objectRef::Instance Method 

UnBound接收机我们使用类名来调用的方法等:

ClassName::Instance Method. 

我有以下问题:

  1. 实例方法需要不同类型的方法引用吗?
  2. BoundUnbound接收方法参考有什么区别?
  3. 我们应该在哪里使用Bound接收器,我们应该在哪里使用Unbound接收器?

我还发现BoundUnbound接收机的解释从Java 8 language features books,但仍与实际的概念混淆。

回答

7

未结合的接收机如String::length的想法是,你指的是 方法到将作为拉姆达的参数中的一个被提供的对象。例如, 可将lambda表达式(String s) -> s.toUpperCase()重写为String::toUpperCase

但有界是指当您调用 拉姆达至外部对象已存在的方法。例如,lambda表达式() -> expensiveTransaction.getValue()可以重写为expensiveTransaction::getValue

情况为参考方法三种不同的方式

(args) -> ClassName.staticMethod(args) 可以ClassName::staticMethod

(arg0, rest) -> arg0.instanceMethod(rest) 可以ClassName::instanceMethodarg0ClassName类型)

(args) -> expr.instanceMethod(args) 可以expr::instanceMethod

回答Java 8 in Action book

6

基本上未绑定的接收器允许您使用实例方法,如果他们与声明类型的第一个参数的静态方法 - 因此你可以通过在你想要的任何实例中使用的功能。对于绑定的接收器,“目标”实例实际上是该函数的一部分。

一个例子可以说明清楚:

import java.util.function.*; 

public class Test { 

    private final String name; 

    public Test(String name) { 
     this.name = name; 
    } 

    public static void main(String[] args) { 
     Test t1 = new Test("t1"); 
     Test t2 = new Test("t2"); 

     Supplier<String> supplier = t2::method; 
     Function<Test, String> function = Test::method; 

     // No need to say which instance to call it on - 
     // the supplier is bound to t2    
     System.out.println(supplier.get()); 

     // The function is unbound, so you need to specify 
     // which instance to call it on 
     System.out.println(function.apply(t1)); 
     System.out.println(function.apply(t2)); 
    } 

    public String method() { 
     return name; 
    } 
} 
+0

一个小的查询。你已经写道:供应商 supplier = t2 :: method;并提供评论如下://供应商绑定到t1。这是错字错误还是我不正确理解? –

+1

@Ravindrababu:只是一个错字。现在修复... –

2

当你想为某个类的特定实例要执行的方法,您可以使用绑定接收。

例如:

Stream.of("x","y").forEach(System.out::println); 

将上PrintStream一个sepcific实例执行println - 的System.out实例。因此将System.out.println("x")System.out.println("y")作为将该方法引用传递给forEach的结果来执行。

在另一方面,如果你想为一个类的实例未指定要执行的方法,可以使用未绑定的接收器。

例如:

Stream.of("x","y","").filter(String::isEmpty); 

将执行在每个流的String实例isEmpty() - 即"x".isEmpty()"y".isEmpty()"".isEmpty()