Referencias de métodos en Java con ejemplos

Las interfaces funcionales en Java y la función Lambda son requisitos previos necesarios para controlar las referencias de métodos en Java. Como todos sabemos, un método es una colección de declaraciones que realizan alguna tarea específica y devuelven el resultado a la persona que llama. Un método puede realizar alguna tarea específica sin devolver nada. Los métodos nos permiten reutilizar el código sin volver a escribir el código. En este artículo, veremos cómo usar los métodos como valor. 

En Java 8 podemos usar el método como si fueran objetos o valores primitivos, y podemos tratarlos como una variable. El ejemplo muestra la función como una variable en Java:

// This square function is a variable getSquare. 
Function<Integer, Integer> getSquare = i -> i * i; 
SomeFunction(a, b, getSquare); 
// Pass function as a argument to other function easily 

A veces, una expresión lambda solo llama a un método existente. En esos casos, parece claro referirse al método existente por su nombre. Las referencias de métodos pueden hacer esto, son compactas y fáciles de leer en comparación con las expresiones lambda. Una referencia de método es la sintaxis abreviada de una expresión lambda que contiene solo una llamada de método. Esta es la sintaxis general de un 

Sintaxis genérica: referencia del método

A. Para referirse a un método en un objeto 

Object :: methodName 

B. Para imprimir todos los elementos en una lista

A continuación se muestra una ilustración de una expresión lambda que solo llama a un único método en toda su ejecución: 

list.forEach(s -> System.out.println(s));  

C. Atajo para imprimir todos los elementos en una lista 

Para que el código sea claro y compacto, en el ejemplo anterior, uno puede convertir la expresión lambda en una referencia de método:

list.forEach(System.out::println);  

Las referencias de métodos solo se pueden usar para reemplazar un solo método de la expresión lambda. Un código es más claro y breve si se usa una expresión lambda en lugar de una clase anónima y se puede usar la referencia de método en lugar de usar una expresión lambda de función única para lograr lo mismo. En general, uno no tiene que pasar argumentos a las referencias de métodos.

El siguiente ejemplo trata sobre cómo realizar algunas operaciones en los elementos de la lista y agregarlos. La operación que se realizará en los elementos es un argumento de función y la persona que llama puede pasar en consecuencia. 

Ilustración:

public int transformAndAdd(List<Integer> l,
                           Function<Integer, Integer> ops) {
    int result = 0;
    for (Integer s : l)
        result += f.apply(s);

    return results;
}

// Operations utility class
class OpsUtil {

    // Method 1
    // To half the variable
    public static Integer doHalf(Integer x) {
        return x / 2;
    }

    // Method 2
    // Square up the integer number
    public static Integer doSquare(Integer x) {

        return x * x;
    }
    
    ... many more operations...
}

Las siguientes son las formas de llamar al método anterior como se muestra a continuación:

List<Integer> list = new ArrayList<>();
// Add some element to list
...
// Using an anonymous class
transformAndAdd(list, new Function<Integer, Integer>() {
    public Integer apply(Integer i) {
        // The method
        return OpsUtil.doHalf(i);
    }
});

// Using a lambda expression
tranformAndAdd(list, i -> OpsUtil.doHalf(i));

// Using a method reference
tranformAndAdd(list, OpsUtil::doHalf);

Tipos de referencias de métodos 

Hay cuatro tipos de referencias de métodos que son los siguientes:

  1. Referencia de método estático.
  2. Instancia Método Referencia de un objeto en particular.
  3. Instancia Método Referencia de un objeto arbitrario de un tipo particular.
  4. Referencia del constructor.

Para analizar todos estos tipos, consideraremos un ejemplo común de clasificación con un comparador que es el siguiente:

Tipo 1: Referencia a un método estático

Si una expresión Lambda es como:

// Si una expresión lambda simplemente llama a un método estático de una clase 
(args) -> Class.staticMethod(args)  

Entonces la referencia del método es como:

// Taquigrafía si una expresión lambda simplemente llama a un método estático de una clase 
Class::staticMethod  

Ejemplo:

Java

// Java Program to Illustrate How One can use
// Static method reference
// To Sort with Custom Comparator
 
// Importing required classes
import java.io.*;
import java.util.*;
 
// Class 1
// Helper class
// Object need to be sorted
class Person {
 
    private String name;
    private Integer age;
 
    // Constructor
    public Person(String name, int age)
    {
        // This keyword refers to current instance itself
        this.name = name;
        this.age = age;
    }
 
    // Getter-setters
    public Integer getAge() { return age; }
    public String getName() { return name; }
}
 
// Class 2
// Main class
public class GFG {
 
    // Method 1
    // Static method to compare with name
    public static int compareByName(Person a, Person b)
    {
        return a.getName().compareTo(b.getName());
    }
 
    // Method 2
    // Static method to compare with age
    public static int compareByAge(Person a, Person b)
    {
        return a.getAge().compareTo(b.getAge());
    }
 
    // Method 3
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an empty ArrayList of user-defined type
        // List of person
        List<Person> personList = new ArrayList<>();
 
        // Adding elements to above List
        // using add() method
        personList.add(new Person("vicky", 24));
        personList.add(new Person("poonam", 25));
        personList.add(new Person("sachin", 19));
 
        // Using static method reference to
        // sort array by name
        Collections.sort(personList, GFG::compareByName);
 
        // Display message only
        System.out.println("Sort by name :");
 
        // Using streams over above object of Person type
        personList.stream()
            .map(x -> x.getName())
            .forEach(System.out::println);
 
        // Now using static method reference
        // to sort array by age
        Collections.sort(personList, GFG::compareByAge);
 
        // Display message only
        System.out.println("Sort by age :");
 
        // Using streams over above object of Person type
        personList.stream()
            .map(x -> x.getName())
            .forEach(System.out::println);
    }
}
Producción: 

Sort by name :
poonam
sachin
vicky
Sort by age :
sachin
vicky
poonam

 

Tipo 2: Referencia a un método de instancia de un objeto en particular

Si una expresión Lambda es como:

// Si una expresión lambda simplemente llama a un método predeterminado de un objeto 

(argumentos) -> obj.instanceMethod(argumentos) 

Entonces la referencia del método es como:

// Taquigrafía si una expresión lambda simplemente llama a un método predeterminado de un objeto 

obj::instanceMethod 

Ejemplo:

Java

// Java Program to Illustrate How One can use
// Static method reference
// To Sort with Custom Comparator
// But using object method reference
 
// Importing required classes
import java.io.*;
import java.util.*;
 
// Class 1
// Helper class
// Object need to be sorted
class Person {
 
    // Attributes of a person
    private String name;
    private Integer age;
 
    // Constructor
    public Person(String name, int age)
    {
        // This keyword refers to current object itself
        this.name = name;
        this.age = age;
    }
 
    // Getter-setter methods
    public Integer getAge() { return age; }
    public String getName() { return name; }
}
 
// Class 2
// Helper class
// Comparator class
class ComparisonProvider {
 
    // Method 1
    // To compare with name
    public int compareByName(Person a, Person b)
    {
        return a.getName().compareTo(b.getName());
    }
 
    // Method 2
    // To compare with age
    public int compareByAge(Person a, Person b)
    {
        return a.getAge().compareTo(b.getAge());
    }
}
 
// Class 3
// Main class
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an empty ArrayList of user-defined type
        // List of person
        List<Person> personList = new ArrayList<>();
 
        // Adding elements to above object
        // using add() method
        personList.add(new Person("vicky", 24));
        personList.add(new Person("poonam", 25));
        personList.add(new Person("sachin", 19));
 
        // A comparator class with multiple
        // comparator methods
        ComparisonProvider comparator
            = new ComparisonProvider();
 
        // Now using instance method reference
        // to sort array by name
        Collections.sort(personList,
                         comparator::compareByName);
 
        // Display message only
        System.out.println("Sort by name :");
 
        // Using streams
        personList.stream()
            .map(x -> x.getName())
            .forEach(System.out::println);
 
        // Using instance method reference
        // to sort array by age
        Collections.sort(personList,
                         comparator::compareByAge);
 
        // Display message only
        System.out.println("Sort by age :");
 
        personList.stream()
            .map(x -> x.getName())
            .forEach(System.out::println);
    }
}
Producción: 

Sort by name :
poonam
sachin
vicky
Sort by age :
sachin
vicky
poonam

 

Tipo 3: Referencia a un método de instancia de un objeto arbitrario de un tipo particular

Si una expresión Lambda es como:

// Si una expresión lambda simplemente llama a un método de instancia de un ObjectType 

(obj, argumentos) -> obj.instanceMethod(argumentos) 

Entonces la referencia del método es como:

// Taquigrafía si una expresión lambda simplemente llama a un método de instancia de un ObjectType 

ObjectType::instanceMethod 

Ejemplo:

Java

// Java Program to Illustrate how One can use
// Instance type method reference to
// sort with custom comparator
 
// Importing required classes
import java.io.*;
import java.util.*;
 
// Main class
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating an empty ArrayList of user defined type
        // List of person
        List<String> personList = new ArrayList<>();
 
        // Adding elements to above object of List
        // using add() method
        personList.add("vicky");
        personList.add("poonam");
        personList.add("sachin");
 
        // Method reference to String type
        Collections.sort(personList,
                         String::compareToIgnoreCase);
 
        // Printing the elements(names) on console
        personList.forEach(System.out::println);
    }
}
Producción: 

poonam
sachin
vicky

 

Tipo 4: referencia de método de constructor

Si una expresión Lambda es como: 

// Si una expresión lambda simplemente crea un objeto 
(args) -> new ClassName (args) 

Entonces la referencia del método es como: 

// Taquigrafía si una expresión lambda simplemente crea un objeto 
ClassName::new 

Ejemplo:

Java

// Java Program to Illustrate How We can Use
// constructor method reference
 
// Importing required classes
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.function.*;
 
// Object need to be sorted
class Person {
    private String name;
    private Integer age;
 
    // Constructor
    public Person()
    {
        Random ran = new Random();
 
        // Assigning a random value
        // to name
        this.name
            = ran
                  .ints(97, 122 + 1)
                  .limit(7)
                  .collect(StringBuilder::new,
                           StringBuilder::appendCodePoint,
                           StringBuilder::append)
                  .toString();
    }
 
    public Integer getAge()
    {
        return age;
    }
    public String getName()
    {
        return name;
    }
}
 
public class GFG {
 
    // Get List of objects of given
    // length and Supplier
    public static <T> List<T>
    getObjectList(int length,
                  Supplier<T> objectSupply)
    {
        List<T> list = new ArrayList<>();
 
        for (int i = 0; i < length; i++)
            list.add(objectSupply.get());
        return list;
    }
 
    public static void main(String[] args)
    {
 
        // Get 10 person by supplying
        // person supplier, Supplier is
        // created by person constructor
        // reference
        List<Person> personList
            = getObjectList(5, Person::new);
 
        // Print names of personList
        personList.stream()
            .map(x -> x.getName())
            .forEach(System.out::println);
    }
}
Producción: 

vzskgmu
iupltfx
kocsipj
lyvhxsp
hbdphyv

 

Conclusión: como se mencionó anteriormente, si una expresión lambda solo llama a un método existente, usar la referencia del método puede hacer que el código sea más legible y claro. Hay muchas más cosas que podemos hacer con Java8 Lambda y Method References mientras usamos flujos de Java.

Publicación traducida automáticamente

Artículo escrito por vickyrathod y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *