Instance method reference and lambda parameters

Itโ€™s hard for me to understand the syntax of a method reference, where there are two parameters a and b , and the reference is to method a on b .

For example, I understand how

 Arrays.sort(personArray, comparators::compareByName); 

equivalently

 Arrays.sort(personArray, (o1, o2) -> comparators.compareByName(o1, o2)); 

because in this case the lambda parameters correspond to the method call parameters (o1, o2) .

Let's say this lambda

 stream.sorted((o1, o2) -> o1.compareToIgnoreCase(o2)); 

my IDE tells me this is equivalent to:

 stream.sorted(String::compareToIgnoreCase); 

and I did not find a rule to replace this syntax: a.method(b) with a reference to a method.

For example, what if there are three or more parameters in a lambda? It is legal? The first parameter becomes the target of the method, and the rest become parameters?

+5
source share
2 answers

I think you are looking for JLS section 15.13.3 , which includes:

If the form ReferenceType :: [TypeArguments] Identifier , the body of the invocation method likewise affects the invocation expression of the method to declare the compilation time, which is the declaration of the compilation time of the method reference expression. An estimate of the execution time of a method invocation expression is defined in ยง 15.12.4.3, ยง 15.12.4.4 and ยง15.12.4.5, where:

  • The call mode is derived from the compilation time declaration, as specified in 15.12.3.

  • If the compile-time declaration is an instance method, then the target link is the first formal parameter of the invocation method. Otherwise, the destination link is missing.

  • If the compilation time declaration is an instance method, then the arguments for expressing the method invocation (if any) are the second and subsequent formal parameters of the invocation method. Otherwise, the arguments to the method invocation expression are the formal parameters of the invocation method.

Pay attention to the last two bullets, basically.

For example, what if there are three or more parameters in a lambda? It is legal? The first parameter becomes the target of the method, and the rest become parameters?

Yup :)

+5
source

I would give a few examples here for those who find the Oracle documentation a bit more complicated. Imagine you need a reference to an instance of Comparator:

 .sorted(String::compareTo) 

String :: compareTo is identical:

 (String a, String b) -> a.compareTo(b); 

Since, as John explained, the method reference will be converted to a lambda that will expect 2 parameters. The actual arbitrary object passed in the stream as the first argument, and one more parameter (since the comparator expects int compare(T o1, T o2) ). Another case:

 .map(Employee::getSalary) 

In this case, the card expects: Function. The function requires an implementation of R apply(T var1) - a method with 1 argument. In this case, the only parameter that will pass the lambda is the actual arbitrary object - an instance on Employee.

To summarize - depending on the context of the compilation time, a method reference to an arbitrary object will always be โ€œtransformedโ€ into a lambda, which expects this object to become the first parameter + any number of parameters that the target method requires in the same corresponding order.

0
source

Source: https://habr.com/ru/post/1201177/


All Articles