Références de méthode en Java

1. Vue d'ensemble

L'un des changements les plus bienvenus dans Java 8 a été l'introduction d'expressions lambda, car elles nous permettent de renoncer aux classes anonymes, ce qui réduit considérablement le code standard et améliore la lisibilité.

Les références de méthode sont un type spécial d'expressions lambda . Ils sont souvent utilisés pour créer des expressions lambda simples en référençant des méthodes existantes.

Il existe quatre types de références de méthode:

  • Méthodes statiques
  • Méthodes d'instance d'objets particuliers
  • Méthodes d'instance d'un objet arbitraire d'un type particulier
  • Constructeur

Dans ce didacticiel, nous explorerons les références de méthodes en Java.

2. Référence à une méthode statique

Nous allons commencer par un exemple très simple, mettant en majuscule et imprimant une liste de chaînes :

List messages = Arrays.asList("hello", "baeldung", "readers!");

Nous pouvons y parvenir en tirant parti d'une simple expression lambda appelant directement la méthode StringUtils.capitalize () :

messages.forEach(word -> StringUtils.capitalize(word));

Ou, nous pouvons utiliser une référence de méthode pour simplement faire référence à la méthode statique capitalize :

messages.forEach(StringUtils::capitalize);

Notez que les références de méthode utilisent toujours l' opérateur :: .

3. Référence à une méthode d'instance d'un objet particulier

Pour illustrer ce type de référence de méthode, considérons deux classes:

public class Bicycle { private String brand; private Integer frameSize; // standard constructor, getters and setters } public class BicycleComparator implements Comparator { @Override public int compare(Bicycle a, Bicycle b) { return a.getFrameSize().compareTo(b.getFrameSize()); } }

Et, créons un objet BicycleComparator pour comparer les tailles de cadre de vélo:

BicycleComparator bikeFrameSizeComparator = new BicycleComparator();

Nous pourrions utiliser une expression lambda pour trier les vélos par taille de cadre, mais nous aurions besoin de spécifier deux vélos à des fins de comparaison:

createBicyclesList().stream() .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));

Au lieu de cela, nous pouvons utiliser une référence de méthode pour que le paramètre de handle du compilateur nous passe:

createBicyclesList().stream() .sorted(bikeFrameSizeComparator::compare);

La référence de la méthode est beaucoup plus claire et plus lisible, car notre intention est clairement indiquée par le code.

4. Référence à une méthode d'instance d'un objet arbitraire d'un type particulier

Ce type de référence de méthode est similaire à l'exemple précédent, mais sans avoir à créer un objet personnalisé pour effectuer la comparaison.

Créons une liste d' entiers que nous voulons trier:

List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);

Si nous utilisons une expression lambda classique, les deux paramètres doivent être explicitement passés, tandis que l'utilisation d'une référence de méthode est beaucoup plus simple:

numbers.stream() .sorted((a, b) -> a.compareTo(b)); numbers.stream() .sorted(Integer::compareTo);

Même s'il s'agit toujours d'une ligne unique, la référence de la méthode est beaucoup plus facile à lire et à comprendre.

5. Référence à un constructeur

Nous pouvons référencer un constructeur de la même manière que nous avons référencé une méthode statique dans notre premier exemple. La seule différence est que nous utiliserons le nouveau mot-clé.

Créons un tableau Bicycle à partir d'une liste de chaînes avec différentes marques:

List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");

Tout d'abord, nous allons ajouter un nouveau constructeur à notre classe Bicycle :

public Bicycle(String brand) { this.brand = brand; this.frameSize = 0; } 

Ensuite, nous utiliserons notre nouveau constructeur à partir d'une référence de méthode et créerons un tableau Bicycle à partir de la liste String d' origine :

bikeBrands.stream() .map(Bicycle::new) .toArray(Bicycle[]::new); 

Remarquez comment nous avons appelé les constructeurs Bicycle et Array en utilisant une référence de méthode, donnant à notre code une apparence beaucoup plus concise et claire.

6. Exemples et limitations supplémentaires

As we've seen so far, method references are a great way to make our code and intentions very clear and readable. However, we can't use them to replace all kinds of lambda expressions since they have some limitations.

Their main limitation is a result of what's also their biggest strength: the output from the previous expression needs to match the input parameters of the referenced method signature.

Let's see an example of this limitation:

createBicyclesList().forEach(b -> System.out.printf( "Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));

This simple case can't be expressed with a method reference, because the printf method requires 3 parameters in our case, and using createBicyclesList().forEach() would only allow the method reference to infer one parameter (the Bicycle object).

Enfin, explorons comment créer une fonction sans opération pouvant être référencée à partir d'une expression lambda.

Dans ce cas, nous souhaitons utiliser une expression lambda sans utiliser ses paramètres.

Tout d'abord, créons la méthode doNothingAtAll :

private static  void doNothingAtAll(Object... o) { }

Comme il s'agit d'une méthode varargs, elle fonctionnera dans n'importe quelle expression lambda, quel que soit l'objet référencé ou le nombre de paramètres déduits.

Maintenant, voyons-le en action:

createBicyclesList() .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o)); 

7. Conclusion

Dans ce rapide tutoriel, nous avons appris quelles sont les références de méthode en Java et comment les utiliser pour remplacer les expressions lambda, améliorant ainsi la lisibilité et clarifiant l'intention du programmeur.

Tout le code présenté dans cet article est disponible à l'adresse over sur GitHub.