使用方法引用而不是多参数lambda

时间:2014-04-17 17:32:04

标签: java lambda java-8

我对背后的概念感到困惑"参考特定类型的任意对象的实例方法"。 Oracle documentation有一个例子:

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

我在这种方法参考中看到的大多数示例都是这样的:如果lambda类似于:x -> x.func(),那么你可以像ClassOfX::func一样编写它。文档中的示例说:

  

方法引用的等效lambda表达式   String :: compareToIgnoreCase将具有形式参数列表   (String a,String b),其中a和b是用于更好的任意名称   描述这个例子。方法引用将调用该方法   a.compareToIgnoreCase(b)中。

问题是:对于任何两个参数lambda,如(a, b) -> a.func(b)func方法必须是第一个参数的实例方法,而lambda的第二个参数将作为参数传递给该方法?如果我们有多个参数lambda,那么func方法必须是lambda的第一个参数的实例方法,而lambda的其他参数将按照lambda中出现的顺序传递给func?我的意思是代替(a, b, c) -> a.func(b, c)我们可以写ClassOfA::func

对不起我的英语。我希望我能明白这个问题。

4 个答案:

答案 0 :(得分:19)

SomeClass::func可能意味着两件事,具体取决于func是静态方法还是实例方法。

(1)如果func是静态方法,则SomeClass::func是一个lambda,它只传递方法的所有参数:

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

(2)如果func是一个实例方法,那么SomeClass::func是一个lambda,它使用第一个参数作为实例,如您所愿:

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

其中a的类型为SomeClass

编辑: Sotirios'回答演示了一种不同类型的方法引用:example::method其中example是引用变量(而不是类名)。这意味着与

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

或者更准确地说

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

其中__someFinalTemporary在评估方法引用的位置分配给example,以便如果example稍后更改,则仍使用较早的{{{}值调用该方法。 1}}。

[第四种是example,它将参数传递给构造函数。我认为这就是全部。]

答案 1 :(得分:8)

这是一个演示实例方法引用行为的小例子。

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);
    }
}

打印

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

这两者或多或少相当。在lambda的情况下,调用方法的变量需要有效final

答案 2 :(得分:5)

  

我的意思是代替(a,b,c) - &gt; a.func(b,c)我们可以编写ClassOfA :: func

是的,这是对的。

答案 3 :(得分:0)

根据Joshua Bloch的“ Effective Java”(第3版),有5种类型的用例可供方法参考。

enter image description here