¿Eres un programador apasionado por Java? Si es así, estás a punto de descubrir una técnica poderosa que revolucionará tu forma de programar. En este artículo, aprenderás a utilizar interfaces funcionales para pasar tus métodos como parámetros en Java. Además, te sumergirás en el fascinante mundo del patrón Callback.
Nuestro primer paso será identificar el tipo de retorno de la función que queremos pasar.
Esto nos sirve entre otras cosas para entender de que manera se va a usar la función.
| Clase | Tipo de retorno original del método | Parámetro original del método | Uso | Método de la interfaz funcional |
|---|---|---|---|---|
| Consumer | void | subtipo de Object | Hacer algo con datos | apply |
| Predicate | boolean | subtipo de Object | Validación | test |
| Supplier | subtipo de Object | sin parámetros | Generar datos | get |
| Function | subtipo de Object | subtipo de Object | Convertir datos | apply |
| Runnable | void | sin parámetros | Ejecutar una acción | run |
A partir de Java 8 tenemos las interfaces funcionales que básicamente son interfaces con un método único, lo que nos permite en sintaxis ahorrarnos mucho código, ya que la implementación es trivial (o talacha como diríamos los mexicanos), y como es trivial podemos en su lugar usar un lambda.
Supongamos que tenemos una función como esta
public void funcionCerrar() {
System.exit(0);
} Este es el caso ideal para un Runnable, si queremos usar este método podemos llamarlo desde la misma clase como
private void ponerEscucha(JButton boton, Runnable miMetodo) {
boton.addActionListener(e -> miMetodo.run());
} Supongamos que tenemos un método con una decisión como un switch
public boolean isTechnicalFighter(String name) {
return switch (name) {
case "El Santo" -> true;
case "El cavernario" -> false;
case "El bulldog" -> false;
default -> false;
};
} En este caso lo ideal es usar un Predicate
public boolean isTechnical(String nombreLuchador, Predicate<String> predicate) {
return predicate.test(nombreLuchador);
} Por ejemplo si tenemos una función para ayudarnos a crear objetos como al siguiente
public JButton creaBotón(String texto) {
return new JButton(texto);
} Lo ideal en este caso es usar una función
private void creacion(String textoBotón, Function<String, JButton> creaBoton) {
creaBoton.apply(textoBotón);
} Recuerda que el primer parámetro del genérico será el tipo de dato de entrada y el segundo el tipo de dato de salida
Para este caso en particular el ejemplo más básico sería obtener un valor aleatoriamente
public int numeroDeLASuerte() {
return (int) (Math.random() * 100);
} Y el tipo para este caso sería un Supplier
private void imprimeNumeroDeLaSuerte(Supplier<Integer> numeroDeLASuerte) {
System.out.println(numeroDeLASuerte.get());
} Si quieres ver más ejemplos, junto con la explicación de que es un lambda revisa mi artículo sobre generadores.
Sencillo, mediante una referencia estática.
Como principio si nuestro método tiene como modificador la palabra static, usaremos el nombre de la clase seguido del operador :: y luego pondremos el nombre de la función
this.ponerEscuchar(this.jButton1, CerrarBotonListener::funcionCerrar); En caso de que no tenga static, usaremos la palabra reservada this para referenciar la instancia actual de la clase seguido del operador :: y luego pondremos el nombre de la función
this.ponerEscuchar(this.jButton1, this::funcionCerrar); al usar esta notación no necesitaremos especificar si es un Consumer, Predicate, Supplier, Runnable o Function.
Si por alguna razón deseamos tener como variable la función sí deberemos declarar el tipo de interfaz funcional que es, por ejemplo, si es un Consumer
Consumer<String> greetPrinter= greeting-> System.out.println(greeting); o si es un supplier
Supplier<String[]> luchadorSupplier = () -> {
return new String[]{"El Santo", "El Cavernario", "Blue Demon", "Bull Dog"};
}; Si bien especificar el tipo de datos de los parámetros usando genéricos es opcional, es una buena práctica ya que nos asegura que nuestros métodos van a funcionar de manera correcta y sin sorpresas, para Runnable nunca se especifica.
Si bien la Tabla 1 es útil, en algunos casos obtendremos código que a pesar de ser corto es un poco confuso. Para evitar eso hay especializaciones de algunas de las clases y las veremos a continuación.
Su principal uso es cuando deseas agregar el Stream API a tu código existente.
¡Enhorabuena! Ahora estás equipado con una potente técnica de programación en Java que te ayudará a optimizar tus proyectos mientras haces muy poco código. Si deseas explorar más sobre este fascinante tema o tienes alguna pregunta, no dudes en explorar este sitio para obtener más recursos y tutoriales. ¡A tirar código al fallo!
Te comparto aquí mis recomendaciones de cursos de Código Facilito. Codigofacilito.com es una plataforma virtual…
Te comparto aquí mis recomendaciones de cursos de Linkedin Learning. LinkedIn Learning es una plataforma…
Estos snippets de código para entrevista acerca de mockito espero te sean de mucha utilidad.…
En este tutorial aprenderá a usar expresiones regulares en Java de manera práctica para contar…
¿Entrevista de programación Java fullstack? No te preocupes, te tengo un compendio de preguntas de…
Te recomiendo algunos cursos de Udemy para mejorar tus softskills y así mejorar en tu…