usar tutorial streams procesamiento parte instrucciones funciones expresiones explicacion datos con como anonimas java lambda java-8

java - tutorial - Usando referencia de método en lugar de multi argumento lambda



java 8 tutorial (3)

Quiero decir en lugar de (a, b, c) -> a.func (b, c) podemos escribir ClassOfA :: func

Si eso es correcto.

Estoy confundido sobre el concepto detrás de "Referencia a un Método de instancia de un Objeto arbitrario de un Tipo particular". La documentación de Oracle tiene un ejemplo sobre esto:

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

La mayoría de los ejemplos que he visto para este tipo de referencia de método es así: si lambda es como: x -> x.func() entonces puedes escribirlo como ClassOfX::func . El ejemplo en la documentación dice:

La expresión lambda equivalente para el método de referencia String :: compareToIgnoreCase tendría la lista de parámetros formales (String a, String b), donde a y b son nombres arbitrarios que se utilizan para describir mejor este ejemplo. La referencia al método invocaría el método a.compareToIgnoreCase (b).

La pregunta es: ¿para dos argumentos lambda como (a, b) -> a.func(b) el método func debe ser el método de instancia del primer argumento y el segundo argumento de lambda se pasará como un argumento para ese método? Si tenemos múltiples argumentos lambda, entonces el método func debe ser el método de instancia del primer argumento de lambda y otros argumentos de lambda se pasarán a func en el orden en que aparecen en lambda. Quiero decir en lugar de (a, b, c) -> a.func(b, c) podemos escribir ClassOfA::func

Lo siento por mi Inglés. Espero haber aclarado el problema.


Aquí hay un pequeño ejemplo que demuestra el comportamiento de una referencia de método de instancia.

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

Imprime

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

Los dos son más o menos equivalentes. En el caso de lambda, la variable sobre la que se invoca el método debe ser efectivamente final .


SomeClass::func puede significar dos cosas, dependiendo de si func es un método estático o un método de instancia.

(1) Si func es un método estático, entonces SomeClass::func es un lambda que pasa todos los argumentos al método:

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

(2) Si func es un método de instancia, entonces SomeClass::func es un lambda que usa el primer argumento como instancia, como pensaste:

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

donde a tiene tipo SomeClass .

EDITAR: La respuesta de Sotirios demuestra aún un tipo diferente de referencia de método: example::method donde el example es una variable de referencia (en lugar de un nombre de clase). Esto significa lo mismo que

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

o tal vez con más precisión

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

donde __someFinalTemporary se asigna al example en el punto donde se evalúa la referencia del método, de modo que si el example cambia más tarde, el método se sigue llamando utilizando el valor anterior de example .

[El cuarto tipo es SomeClass::new que pasa los argumentos a un constructor. Creo que eso es todo de ellos.]