简体   繁体   English

使用方法引用代替多参数lambda

[英]Using method reference instead of multi argument lambda

I'm confused about concept behind "Reference to an Instance Method of an Arbitrary Object of a Particular Type". 我对“引用特定类型的任意对象的实例方法”背后的概念感到困惑。 Oracle documentation has an example about this: Oracle 文档提供了有关此示例:

String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

Most of the examples I have seen for this kind of method reference is like this: If lambda is like: x -> x.func() then you can write it like ClassOfX::func . 我为这种方法参考看到的大多数示例都是这样的:如果lambda是这样的: x -> x.func()那么您可以像ClassOfX::func那样编写它。 The example in documentation says: 文档中的示例说:

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. 方法参考String :: compareToIgnoreCase的等效lambda表达式将具有形式参数列表(字符串a,字符串b),其中a和b是用于更好地描述此示例的任意名称。 The method reference would invoke the method a.compareToIgnoreCase(b). 方法引用将调用方法a.compareToIgnoreCase(b)。

The question is: for any two argument lambda like (a, b) -> a.func(b) the func method must be instance method of first argument and second argument of lambda will be passed as an argument to that method? 问题是:对于像(a, b) -> a.func(b)这样的任意两个参数lambda (a, b) -> a.func(b) func方法必须是第一个参数的实例方法,而lambda的第二个参数将作为参数传递给该方法? If we have multiple argument lambda then func method must be instance method of first argument of lambda and other arguments of lambda will be passed to func in the order the appear in lambda? 如果我们有多个参数lambda,则func方法必须是lambda的第一个参数的实例方法,而lambda的其他参数将按在lambda中出现的顺序传递给func I mean instead of (a, b, c) -> a.func(b, c) we can write ClassOfA::func 我的意思是代替(a, b, c) -> a.func(b, c)我们可以编写ClassOfA::func

I'm sorry for my English. 我的英语不好意思。 I hope I made the problem clear. 我希望我能解决这个问题。

SomeClass::func can mean two things, depending on whether func is a static method or an instance method. SomeClass::func可以表示两件事,具体取决于func是静态方法还是实例方法。

(1) If func is a static method, then SomeClass::func is a lambda that just passes all the arguments to the method: (1)如果func是静态方法,则SomeClass::func是一个lambda,它将所有参数传递给该方法:

(a, b, c) -> SomeClass.func(a, b, c);

(2) If func is an instance method, then SomeClass::func is a lambda that uses the first argument as the instance, as you thought: (2)如果func是一个实例方法,那么SomeClass::func是一个lambda,您将第一个参数用作实例,如您所想:

(a, b, c) -> a.func(b, c);

where a has type SomeClass . 其中a类型为SomeClass

EDIT: Sotirios' answer demonstrates yet a different type of method reference: example::method where example is a reference variable (instead of a class name). 编辑: Sotirios的答案演示了方法引用的另一种类型: example::method其中example是引用变量(而不是类名)。 This means the same as 这意味着与

(a, b) -> example.method(a, b);

or perhaps more accurately 或更准确地说

(a, b) -> __someFinalTemporary.method(a, b);

where __someFinalTemporary is assigned to example at the point where the method reference is evaluated, so that if example changes later, the method is still called using the earlier value of example . 其中__someFinalTemporary在评估方法引用的位置分配给example ,因此,如果后来更改了example ,仍将使用example的早期值来调用该方法。

[The fourth kind is SomeClass::new which passes the arguments to a constructor. [第四种是SomeClass::new ,它将参数传递给构造函数。 I think that's all of them.] 我认为这就是全部。]

Here's a small example demonstrating the behavior of an instance method reference. 这是一个演示实例方法引用行为的小示例。

public class Example {  
    public static void main(String[] args) throws Exception {
        List<String> strings = new ArrayList<String>();
        Example example = new Example();
        Functional methodRef = example::method;
        methodRef.funct("a string", strings);
        System.out.println("List now contains: " + strings);

        Functional lambda = (String s, List<String> l) -> {
            example.method(s, l);
        };
        lambda.funct("another string", strings);
        System.out.println("List now contains: " + strings);
    }

    interface Functional {
        void funct(String value, List<String> list);
    }

    void method(String value, List<String> toAddTo) {
        System.out.println("adding");
        toAddTo.add(value);
    }
}

It prints 它打印

adding
List now contains: [a string]
adding
List now contains: [a string, another string]

The two are more or less equivalent. 两者差不多。 In the lambda's case, the variable the method is invoked on needs to be effectively final . 在lambda的情况下,方法被调用的变量必须有效地为final

I mean instead of (a, b, c) -> a.func(b, c) we can write ClassOfA::func 我的意思是代替(a,b,c)-> a.func(b,c)我们可以编写ClassOfA :: func

Yes, that's correct. 对,那是正确的。

According to Joshua Bloch in his "Effective Java" (3rd Edition), there are 5 types of use cases for method reference. 根据Joshua Bloch在其“ Effective Java”(第3版)中的介绍,有5种类型的用例可供方法参考。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM