Java8:方法引用绑定接收器和未绑定接收器之间的差异

Java8:方法引用绑定接收器和未绑定接收器之间的差异,java,lambda,java-8,method-reference,Java,Lambda,Java 8,Method Reference,我试图在代码中使用Java8方法引用。有四种类型的方法引用可用 静态方法参考 实例方法(绑定接收器) 实例方法(未绑定接收器) 构造函数引用 使用静态方法引用和构造函数引用我没有问题,但是实例方法(绑定接收方)和实例方法(未绑定接收方)确实让我困惑。在Boundreceiver中,我们使用对象引用变量调用如下方法: objectRef::Instance Method ClassName::Instance Method. 在UnBoundreceiver中,我们使用类名调用如下方法: ob

我试图在代码中使用Java8方法引用。有四种类型的方法引用可用

  • 静态方法参考
  • 实例方法(绑定接收器)
  • 实例方法(未绑定接收器)
  • 构造函数引用
  • 使用
    静态方法引用
    构造函数引用
    我没有问题,但是
    实例方法(绑定接收方)
    实例方法(未绑定接收方)
    确实让我困惑。在
    Bound
    receiver中,我们使用对象引用变量调用如下方法:

    objectRef::Instance Method
    
    ClassName::Instance Method.
    
    UnBound
    receiver中,我们使用类名调用如下方法:

    objectRef::Instance Method
    
    ClassName::Instance Method.
    
    我有以下问题:

  • 实例方法需要不同类型的方法引用吗
  • Bound
    Unbound
    接收方方法引用之间有什么区别
  • 我们应该在哪里使用
    Bound
    receiver,在哪里使用
    Unbound
    receiver

  • 我还从接收方找到了
    Bound
    Unbound
    的解释,但仍然与实际概念相混淆

    基本上,未绑定的接收器允许您使用实例方法,就像它们是具有声明类型的第一个参数的静态方法一样-因此您可以通过传入任何您想要的实例将它们用作函数。对于绑定接收器,“目标”实例实际上是函数的一部分

    举个例子可以更清楚地说明这一点:

    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;
        }
    }
    
    import java.util.function.*;
    公开课考试{
    私有最终字符串名;
    公共测试(字符串名称){
    this.name=名称;
    }
    公共静态void main(字符串[]args){
    测试t1=新测试(“t1”);
    测试t2=新测试(“t2”);
    供应商=t2::方法;
    函数=测试::方法;
    //无需说明调用它的实例-
    //供应商必须遵守t2
    System.out.println(supplier.get());
    //函数未绑定,因此需要指定
    //在哪个实例上调用它
    System.out.println(function.apply(t1));
    System.out.println(function.apply(t2));
    }
    公共字符串方法(){
    返回名称;
    }
    }
    
    基本上,未绑定的接收器允许您使用实例方法,就好像它们是具有声明类型的第一个参数的静态方法一样-因此您可以通过传入任何需要的实例将它们用作函数。对于绑定接收器,“目标”实例实际上是函数的一部分

    举个例子可以更清楚地说明这一点:

    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;
        }
    }
    
    import java.util.function.*;
    公开课考试{
    私有最终字符串名;
    公共测试(字符串名称){
    this.name=名称;
    }
    公共静态void main(字符串[]args){
    测试t1=新测试(“t1”);
    测试t2=新测试(“t2”);
    供应商=t2::方法;
    函数=测试::方法;
    //无需说明调用它的实例-
    //供应商必须遵守t2
    System.out.println(supplier.get());
    //函数未绑定,因此需要指定
    //在哪个实例上调用它
    System.out.println(function.apply(t1));
    System.out.println(function.apply(t2));
    }
    公共字符串方法(){
    返回名称;
    }
    }
    
    当您希望为某个类的特定实例执行该方法时,可以使用绑定接收器

    例如:

    Stream.of("x","y").forEach(System.out::println);
    
    Stream.of("x","y","").filter(String::isEmpty);
    
    将在
    PrintStream
    的特定实例上执行
    println
    System.out
    实例。因此,将该方法引用传递给
    forEach
    后,将执行
    System.out.println(“x”)
    System.out.println(“y”)

    另一方面,如果希望为类的未指定实例执行该方法,则可以使用未绑定的接收器

    例如:

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

    将在流的每个
    字符串
    实例上执行
    isEmpty()
    ,即
    “x”.isEmpty()
    “y”.isEmpty()
    ”。isEmpty()

    当您希望为某个类的特定实例执行该方法时,您使用绑定接收器

    例如:

    Stream.of("x","y").forEach(System.out::println);
    
    Stream.of("x","y","").filter(String::isEmpty);
    
    将在
    PrintStream
    的特定实例上执行
    println
    System.out
    实例。因此,将该方法引用传递给
    forEach
    后,将执行
    System.out.println(“x”)
    System.out.println(“y”)

    另一方面,如果希望为类的未指定实例执行该方法,则可以使用未绑定的接收器

    例如:

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

    将在流的每个
    字符串
    实例上执行
    isEmpty()
    ,即
    “x”.isEmpty()
    “y”.isEmpty()
    ”。isEmpty()

    未绑定接收器的概念,例如
    字符串::长度
    ,是指 对象的方法,该对象将作为lambda的参数之一提供。例如 lambda表达式
    (String s)->s.toUpperCase()
    可以重写为
    String::toUpperCase

    但是,Bounded指的是在 lambda到已存在的外部对象。例如,lambda表达式
    ()->expensiveTransaction.getValue()
    可以重写为
    expensiveTransaction::getValue

    三种不同方法参考的情况

    (args)->ClassName.staticMethod(args)
    可以是
    ClassName::staticMethod
    //这是静态的(您也可以认为是未绑定的)

    (arg0,rest)->arg0.instanceMethod(rest)
    可以是
    ClassName::ins