¿Qué son los :: en Java?
¿Vas llevando tiempo programando en Java y de repente encuentras que usan esta notación?
String::toUpperCase
Y te preguntas ¿Ya parece C++? ¿Qué es eso? ¿Cómo funciona ese ::
Aquí explicaremos un poco de qué trata.
Supongamos que tenemos una lista de cadenas y queremos tener otra lista con las mismas cadenas pero con el texto en mayúsculas. La manera común es hacer lo siguiente:
var names = Arrays.asList("Ann", "Bob", "Carl", "David"); List<String> namesUpper = new ArrayList<>(); for (String name : names) { namesUpper.add(name.toUpperCase()); }
Sabemos que funciona, con tres instrucciones, en la 11 declaramos la lista de
destino, en la 12 comenzamos un bucle, y en la 13 convertimos cada elemento
del bucle, lo convertimos a mayúscula con el método
String.toUpperCase()
(ojo con esto) y lo agregamos a la lista
declarada en la línea 11.
Ahora, usando programación funcional que ya está disponible a partir de la versión 8 de Java, podemos hacer lo mismo pero usando una sola línea, así:
var names = Arrays.asList("Ann", "Bob", "Carl", "David"); List<String> namesUpper = names.stream() .map((String name) -> { return name.toUpperCase(); }).toList();
La línea 13 es similar a la versión anterior: cada iteración del metodo
map()
tiene como parámetro a name
y lo devuelve
invocando al método String.toUpperCase()
. También se puede
resumir así:
var names = Arrays.asList("Ann", "Bob", "Carl", "David"); List<String> namesUpper = names.stream() .map(name -> name.toUpperCase()) .toList();
El mismo parámetro name
es invocado al método
toUpperCase()
y es devuelto en la función Lambda.
Ahora bien, si ya sabemos que se trata del mismo objeto parámetro del método
map
¿para que mencionarlo nuevamente?. Es algo "redundante", si
es ese, que solo invoque a SU método. Entonces, aquí viene este anotación
curiosa: llamamos a la clase del parámetro y al método que queremos invocar.
El compilador ya sabe que se trata del parámetro.
var names = Arrays.asList("Ann", "Bob", "Carl", "David"); List<String> namesUpper = names.stream() .map(String::toUpperCase) .toList();
¿Podemos pasar parámetros?
Sí, pero solo uno. Veamos este ejemplo. Consideremos un método que solo imprime la longitud de cada cadena, este método es simple:
static void printLength(int size) { System.out.println("size:" + size); // muy complejo, XD }
Ahora, lo que haremos es, tomar la longitud de cada cadena (usando el método
String.length
) similar al ejemplo anterior, y luego invocamos al
método que acabamos de crear. Así que, primero debemos tomar el valor del
método, usamos map
y luego, por cada ejemplo con -
forEach
- usamos el método printLength
. Primero lo
haremos usando parámetros:
public class Ejemplos { public static void main(String[] args) { var names = Arrays.asList("Ann", "Bob", "Carl", "David"); names.stream() .map(name -> name.length()) .forEach( length -> Ejemplos.printLength(length) ); } static void printLength(int size) { System.out.println("size:" + size); } }
- Línea 10: Extraemos la longitud de cada cadena y se lo pasamos al siguiente método de la llamada funcional.
-
Línea 11: Allí llega como parámetro el valor del método anterior, y allí
invocamos al método
Ejemplos.printLength()
, y como argumento le pasamos el parámetro recibido.
Ahora, lo podemos reducir con la notación especial:
var names = Arrays.asList("Ann", "Bob", "Carl", "David"); names.stream() .map(String::length) .forEach(Ejemplos::printLength);
La línea 10 ya la conocemos, pero la línea 11 es nueva: La notación sabe que
el parámetro que está recibiendo (si está llegando) es enviado como argumento
al método Ejemplos.printLength
.
Esta es la explicación y el uso de la misteriosa notación de los dos puntos
::
.
Si te gustó y es útil, comparte que es gratis.
Hola explicas con ejemplo... pero, mi primera pregunta, ¿Es cómo se llama en java los ::? ... luego lo que logre entender es que se llama a un método de la clase con los dos puntos.... sería clase::Metodo... ¿Puede ser cualquier método de la clase?
ResponderBorrarHola Carlo, así es, cualquier método PERO que cumpla las siguientes reglas: que sea accesible desde donde se llama (o sea, que cumpla el alcance de public, protected, privated, etc...), que no tenga ningún parámetro o que tenga un solo parámetro que sea del mismo tipo del parámetro que viene de la invocación.
BorrarEso de la invocación lo mencionaré en un siguiente post sobre "programación funcional en Java, la notación 'Flecha' "
hmm todo ok con los ejemplos pero deberías de centrarte o enfocar mas en los :: osea ser un poco mas directo pero igual se agradece
ResponderBorrar