Referencia de método de instancia y parámetros de Lambda

Tengo problemas para entender la syntax de una referencia de método, donde hay dos parámetros a y b , y la referencia es a un método de a en b .

Por ejemplo, entiendo cómo

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

es equivalente a

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

porque en ese caso los parámetros lambda coinciden con los parámetros de llamada del método (o1, o2) .

Sin embargo, para esta lambda

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

mi IDE me dice que es equivalente a:

 stream.sorted(String::compareToIgnoreCase); 

y no estoy encontrando una regla para reemplazar esa syntax: a.method(b) con una referencia de método.

Por ejemplo, ¿qué pasa si hay tres o más parámetros para la lambda? Es eso legal? ¿El primer parámetro se convierte en el objective del método y el rest se convierten en los parámetros?

Creo que estás buscando la sección 15.13.3 de JLS , que incluye:

Si el formulario es ReferenceType :: [TypeArguments] Identifier , el cuerpo del método de invocación tiene el efecto de una expresión de invocación de método para una statement en tiempo de comstackción que es la statement en tiempo de comstackción de la expresión de referencia del método. La evaluación en tiempo de ejecución de la expresión de invocación del método se especifica en §15.12.4.3, §15.12.4.4 y §15.12.4.5, donde:

  • El modo de invocación se deriva de la statement en tiempo de comstackción como se especifica en §15.12.3.

  • Si la statement de tiempo de comstackción es un método de instancia, entonces la referencia de destino es el primer parámetro formal del método de invocación. De lo contrario, no hay referencia de destino.

  • Si la statement en tiempo de comstackción es un método de instancia, los argumentos para la expresión de invocación del método (si hay alguno) son el segundo y posteriores parámetros formales del método de invocación. De lo contrario, los argumentos para la expresión de invocación de método son los parámetros formales del método de invocación.

Tenga en cuenta las dos últimas balas, básicamente.

Por ejemplo, ¿qué pasa si hay tres o más parámetros para la lambda? Es eso legal? ¿El primer parámetro se convierte en el objective del método y el rest se convierten en los parámetros?

Sip 🙂

Daría un par de ejemplos aquí, para aquellos que encuentran que la documentación de Oracle es un poco difícil de asimilar. Imagínese que necesita una referencia a una instancia de Comparator:

 .sorted(String::compareTo) 

String :: compareTo es idéntico a:

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

Porque, como Jon explicó, una referencia de método se transformará en una lambda que esperará 2 parámetros. El objeto arbitrario real pasado en la secuencia como primer argumento y un parámetro más (ya que Comparator espera una int compare(T o1, T o2) ). Otro caso:

 .map(Employee::getSalary) 

En este caso, el mapa espera: Función. La función requiere la implementación de R apply(T var1) , un método con 1 argumento. En este caso, el único parámetro que se pasará a la lambda es el objeto arbitrario real: instancia en Employee.

En resumen, según el contexto de tiempo de comstackción, la referencia de método al objeto arbitrario siempre se “transformará” en una lambda que espera ese objeto como primer parámetro + cualquier cantidad de parámetros que requiera el método de destino en el mismo orden correspondiente.

    Intereting Posts