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.]