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

2022-09-02 05:27:42

我对“引用特定类型的任意对象的实例方法”背后的概念感到困惑。Oracle 文档有一个关于此的示例:

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

我见过的这种方法引用的大多数例子都是这样的:如果lambda是这样的:那么你可以像.文档中的示例说:x -> x.func()ClassOfX::func

方法引用 String::compareToIgnoreCase 的等效 lambda 表达式将具有正式参数列表(字符串 a、字符串 b),其中 a 和 b 是用于更好地描述此示例的任意名称。方法引用将调用方法 a.compareToIgnoreCase(b)。

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

对不起我的英语。我希望我把问题说清楚了。


答案 1

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

(1) 如果 是一个静态方法,则是一个将所有参数传递给该方法的 lambda:funcSomeClass::func

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

(2) 如果 是实例方法,则是使用第一个参数作为实例的 lambda,正如您所想的那样:funcSomeClass::func

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

其中具有 类型 。aSomeClass

编辑:Sotirios的答案展示了一种不同类型的方法参考:其中是参考变量(而不是类名)。这意味着与example::methodexample

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

或者更准确地说

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

where 在计算方法引用的点分配给 ,以便在以后更改时,仍使用较早的值调用方法。__someFinalTemporaryexampleexampleexample

[第四种是将参数传递给构造函数。我想这就是他们所有人。SomeClass::new


答案 2

下面是一个小示例,演示实例方法引用的行为。

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


推荐