CodeGym /Cours /JAVA 25 SELF /Références de méthode (::) : liens vers des méthodes

Références de méthode (::) : liens vers des méthodes

JAVA 25 SELF
Niveau 21, Leçon 1
Disponible

1. Introduction

Method reference (ou en français — « référence de méthode ») est une syntaxe spéciale en Java qui permet de transmettre une méthode (ou un constructeur) existante comme implémentation d’une interface fonctionnelle. On peut « passer » une méthode là où une expression lambda est attendue, si les signatures coïncident.

Syntaxe :

Classe::méthode
objet::méthode
Classe::new

Si une lambda est une mini‑fonction « à la volée », alors une référence de méthode, c’est simplement « passe une méthode déjà existante ». C’est comme, au lieu de réécrire une recette, donner le lien vers la page qui la contient.

Exemple simple

Au lieu de ceci :

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

On peut faire ainsi :

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

C’est concis, n’est-ce pas ?

2. Types de références de méthode

Les références de méthode existent sous quatre formes principales. Les voici — et rien de plus n’est nécessaire.

Référence à une méthode statique

Syntaxe : Classe::methodeStatique

Exemple :

Function<Integer, String> intToString = String::valueOf;
System.out.println(intToString.apply(123)); // "123"

La même chose avec une lambda :

Function<Integer, String> intToString = i -> String.valueOf(i);

Référence à une méthode d’instance d’un objet

Syntaxe : objet::méthode

Exemple :

PrintStream printer = System.out;
Consumer<String> consumer = printer::println;
consumer.accept("Bonjour, le monde!");

Équivalent à une lambda :

Consumer<String> consumer = s -> printer.println(s);

Référence à une méthode d’instance de classe

Syntaxe : Classe::méthode

Ici, le premier paramètre de l’interface fonctionnelle devient l’objet sur lequel la méthode est appelée.

Exemple :

Function<String, Integer> stringLength = String::length;
System.out.println(stringLength.apply("Java")); // 4

Ici, String::length se transforme en fonction : (String s) -> s.length()

Référence à un constructeur

Syntaxe : Classe::new

Exemple :

Supplier<ArrayList<String>> listSupplier = ArrayList::new;
ArrayList<String> list = listSupplier.get();

Équivalent à une lambda :

Supplier<ArrayList<String>> listSupplier = () -> new ArrayList<>();

3. Quand utiliser une référence de méthode ?

La référence de méthode est pratique lorsque la lambda ne fait qu’appeler une méthode existante sans logique supplémentaire — le code devient alors plus court et plus lisible.

Exemple : tri d’une liste

Au lieu de ceci :

List<String> names = Arrays.asList("John", "Peter", "Anna");
names.sort((a, b) -> a.compareToIgnoreCase(b));

On peut écrire :

names.sort(String::compareToIgnoreCase);

Exemple : traitement des collections

Au lieu de :

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

Encore plus court :

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

Exemple : transformation d’éléments

Au lieu de :

List<String> numbers = Arrays.asList("1", "2", "3");
List<Integer> ints = numbers.stream()
    .map(s -> Integer.parseInt(s))
    .collect(Collectors.toList());

On peut :

List<Integer> ints = numbers.stream()
    .map(Integer::parseInt)
    .collect(Collectors.toList());

Vous en saurez plus sur le Stream API et la classe utilitaire Collectors au niveau 30 :P

4. Comparaison entre références de méthode et expressions lambda

Équivalence

La référence de méthode et l’expression lambda sont souvent interchangeables. Les deux réalisent une interface fonctionnelle si les signatures coïncident.

Exemple :

Consumer<String> c1 = s -> System.out.println(s);
Consumer<String> c2 = System.out::println;

Quand vaut-il mieux utiliser une référence de méthode ?

  • Quand la lambda ne fait qu’appeler une méthode existante sans logique supplémentaire.
  • Pour améliorer la lisibilité, surtout dans de longues chaînes d’appels.
  • Quand on veut montrer explicitement : « ici, c’est juste un appel de méthode ».

Quand la référence de méthode ne convient-elle pas ?

  • Si une logique supplémentaire est nécessaire (validation, conditions, gestion d’erreurs).
  • Si les paramètres doivent être transformés avant l’appel de la méthode.

Exemple :

list.forEach(s -> {
    if (s != null) System.out.println(s);
});
// Ici, une référence de méthode ne convient pas, seule une lambda.

5. Pratique : réécrire des expressions lambda à l’aide des références de méthode

Exemple 1 : afficher les noms des animaux

List<String> animals = Arrays.asList("Chat", "Chien", "Perroquet");
animals.forEach(animal -> System.out.println(animal));

Devient :

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

Exemple 2 : convertir des chaînes en nombres

List<String> numbers = Arrays.asList("10", "20", "30");
List<Integer> ints = numbers.stream()
    .map(s -> Integer.parseInt(s))
    .collect(Collectors.toList());

Devient :

List<Integer> ints = numbers.stream()
    .map(Integer::parseInt)
    .collect(Collectors.toList());

Exemple 3 : trier des objets par nom

List<Animal> animalList = ...;
animalList.sort((a, b) -> a.getName().compareTo(b.getName()));

Devient :

animalList.sort(Comparator.comparing(Animal::getName));

Ici, Animal::getName est une référence à une méthode d’instance de classe.

Exemple 4 : créer des objets via un constructeur

Supplier<Dog> dogFactory = () -> new Dog();
Dog dog = dogFactory.get();

Devient :

Supplier<Dog> dogFactory = Dog::new;
Dog dog = dogFactory.get();

6. Comment fonctionne la correspondance des signatures

Une référence de méthode ne peut être utilisée que lorsque la signature de la méthode correspond à celle de la méthode abstraite de l’interface fonctionnelle.

@FunctionalInterface
interface IntToString {
    String convert(int value);
}

public class Demo {
    public static String intToHex(int value) {
        return Integer.toHexString(value);
    }

    public static void main(String[] args) {
        IntToString converter = Demo::intToHex;
        System.out.println(converter.convert(255)); // ff
    }
}

Ici, Demo::intToHex convient, car il prend un int et retourne un String.

7. Références de méthode et constructeurs avec paramètres

Si le constructeur prend des paramètres, on peut quand même utiliser une référence de méthode — à condition que les signatures coïncident.

@FunctionalInterface
interface AnimalFactory {
    Animal create(String name);
}

class Animal {
    private String name;
    public Animal(String name) { this.name = name; }
    public String getName() { return name; }
}

AnimalFactory factory = Animal::new;
Animal cat = factory.create("Buddy");
System.out.println(cat.getName()); // Buddy

8. Erreurs typiques lors de l’utilisation des références de méthode

Erreur n° 1 : incompatibilité des signatures.
Si la signature de la méthode ne correspond pas à celle de la méthode abstraite de l’interface, le compilateur signalera une erreur. Par exemple, l’interface attend deux paramètres, mais la référence pointe vers une méthode avec un seul paramètre.

Erreur n° 2 : tentative d’utiliser une référence à une méthode d’instance de classe sans objet.
Lorsque vous utilisez la forme Classe::méthode, le premier paramètre de l’interface devient l’objet d’appel. Si vous confondez le nombre ou l’ordre des paramètres, vous obtiendrez une erreur de correspondance.

Erreur n° 3 : utiliser une référence de méthode là où une logique supplémentaire est nécessaire.
S’il faut une condition, un logging ou la gestion d’exceptions, utilisez une lambda, pas une référence de méthode.

Erreur n° 4 : références à des méthodes surchargées.
Si une classe possède plusieurs méthodes portant le même nom, le compilateur peut ne pas savoir laquelle choisir. Parfois, indiquer explicitement le type de l’interface fonctionnelle aide.

Erreur n° 5 : utiliser une référence à une méthode d’instance sans objet.
Par exemple, String::toUpperCase fonctionne correctement dans un map, car le premier paramètre est l’objet String lui‑même. Mais hors du contexte approprié, où un appel statique est attendu, cela mènera à une erreur.

1
Mission
JAVA 25 SELF, niveau 21, leçon 1
Bloqué
Convertisseur d'identifiants d'appareils 📟
Convertisseur d'identifiants d'appareils 📟
1
Mission
JAVA 25 SELF, niveau 21, leçon 1
Bloqué
Système de journalisation personnalisé 📝
Système de journalisation personnalisé 📝
1
Mission
JAVA 25 SELF, niveau 21, leçon 1
Bloqué
Organisation de l'inventaire dans l'entrepôt 🍎🍌🍐
Organisation de l'inventaire dans l'entrepôt 🍎🍌🍐
1
Mission
JAVA 25 SELF, niveau 21, leçon 1
Bloqué
Fabrique d'animaux virtuels 🐾
Fabrique d'animaux virtuels 🐾
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION