0Pricing
Java Academy · Leçon

Jokers à borne inférieure

? super T pour les consommateurs

Jokers à borne inférieure est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Le caractère générique à borne inférieure

? super T est un caractère générique à borne inférieure. Cela signifie « un type inconnu qui est T ou un supertype de T ».

List<? super Integer> peut désigner une List<Integer>, une List<Number> ou une List<Object>.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> a = new ArrayList<Number>();
        List<? super Integer> b = new ArrayList<Object>();
        a.add(1);
        b.add(2);
        System.out.println(a + " " + b);
    }
}

Écrire dans un consommateur

Avec ? super Integer, vous pouvez ajouter en toute sécurité n’importe quel entier (ou sous-type d’entier).

Quel que soit le type réel de la liste, il s’agit au moins d’une liste d’un supertype d’entier ; un entier y trouvera donc toujours sa place.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static void addNumbers(List<? super Integer> dest) {
        for (int i = 1; i <= 3; i++) dest.add(i);
    }
    public static void main(String[] args) {
        List<Number> nums = new ArrayList<>();
        addNumbers(nums);
        System.out.println(nums);
    }
}

La lecture ne donne qu’un objet

Le compromis est le suivant : lorsque vous lisez dans une liste ? super T, le compilateur sait seulement que les éléments sont un supertype inconnu de T.

Le seul type sûr pour les lectures est Object.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> list = new ArrayList<Number>();
        list.add(10);
        Object o = list.get(0); // only Object is guaranteed
        // Integer i = list.get(0); // would NOT compile
        System.out.println(o);
    }
}

Pourquoi la lecture est limitée

Une List<? super Integer> pourrait en réalité être une List<Object> contenant des chaînes.

Une lecture pourrait donc renvoyer n’importe quel objet. Le compilateur ne peut pas garantir qu’il s’agit d’un entier ; les lectures ne fournissent donc qu’un objet.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Object> raw = new ArrayList<>();
        raw.add("a string");
        List<? super Integer> view = raw; // legal: Object is a supertype of Integer
        view.add(5);
        System.out.println(view.get(0).getClass().getSimpleName());
    }
}

Cas d’utilisation d’un consommateur

Utilisez ? super T lorsqu’une méthode ne fait que consommer des valeurs (les écrire).

Une méthode qui remplit une collection de destination en est le cas classique.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static void fill(List<? super String> dest, int count) {
        for (int i = 0; i < count; i++) dest.add("item" + i);
    }
    public static void main(String[] args) {
        List<Object> objs = new ArrayList<>();
        fill(objs, 3);
        System.out.println(objs);
    }
}

Les sous-types peuvent aussi être ajoutés

Avec ? super Number, vous pouvez ajouter n’importe quel nombre ou l’un de ses sous-types : un entier, un nombre à virgule ou un entier long.

La borne inférieure garantit que la liste accepte au moins les nombres ; tous leurs sous-types peuvent donc y être ajoutés.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Number> list = new ArrayList<Object>();
        list.add(1);      // Integer
        list.add(2.5);    // Double
        list.add(3L);     // Long
        System.out.println(list);
    }
}

Style Collections.addAll

Le JDK utilise les bornes inférieures pour les destinations. Par exemple, une méthode générique qui ajoute des éléments dans une collection de destination.

import java.util.ArrayList;
import java.util.List;

public class Main {
    @SafeVarargs
    static <T> void addAll(List<? super T> dest, T... items) {
        for (T item : items) dest.add(item);
    }
    public static void main(String[] args) {
        List<Object> sink = new ArrayList<>();
        addAll(sink, "a", "b", "c");
        System.out.println(sink);
    }
}

Comparateur avec une borne inférieure

Voici un cas d’utilisation concret : Comparator<? super T> permet à une opération de tri d’accepter un comparateur écrit pour un supertype.

Un comparateur qui compare n’importe quel objet à l’aide de toString peut trier une liste de chaînes.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Comparator<Object> byString = Comparator.comparing(Object::toString);
        List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
        names.sort(byString); // List<String>.sort accepts Comparator<? super String>
        System.out.println(names);
    }
}

Les bornes supérieure et inférieure sont opposées

Les deux caractères génériques sont opposés :

  • ? extends T : lire T, impossible d’écrire. C’est un producteur.
  • ? super T : écrire T, lire uniquement Object. C’est un consommateur.

Cette symétrie est au cœur de la règle PECS que vous apprendrez ensuite.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> consumer = new ArrayList<Number>();
        consumer.add(1);
        System.out.println("consumer can write: " + consumer);
    }
}

Copier entre des bornes

Une méthode copy montre les deux caractères génériques à la fois : elle lit depuis ? extends T et écrit dans ? super T.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static <T> void copy(List<? extends T> src, List<? super T> dest) {
        for (T t : src) dest.add(t);
    }
    public static void main(String[] args) {
        List<Integer> src = List.of(1, 2, 3);
        List<Number> dest = new ArrayList<>();
        copy(src, dest);
        System.out.println(dest);
    }
}

Quand ne pas utiliser de caractère générique

Si une méthode lit et écrit à la fois des valeurs de type T, n’utilisez pas de caractère générique. Utilisez un type exact ou un paramètre de type nommé.

Les caractères génériques sont précisément faits pour les cas en lecture seule ou en écriture seule.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static <T> void swapFirstTwo(List<T> list) {
        T tmp = list.get(0);
        list.set(0, list.get(1));
        list.set(1, tmp);
    }
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(List.of("a", "b"));
        swapFirstTwo(list);
        System.out.println(list);
    }
}

Vérification rapide

Testez votre compréhension des bornes inférieures.

Récapitulatif

Vous avez appris les caractères génériques à borne inférieure :

  • ? super T désigne un supertype inconnu de T.
  • Vous pouvez écrire T et ses sous-types (un consommateur).
  • Les lectures renvoient uniquement un objet.
  • Ce mécanisme est exactement l’image miroir de ? extends T.

Ensuite, nous verrons la règle qui relie les deux : PECS.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> list = new ArrayList<Number>();
        list.add(42);
        System.out.println("Lower bound recap: " + list);
    }
}

Questions Fréquemment Posées

La leçon « Jokers à borne inférieure » est-elle gratuite ?

Oui — le texte complet de « Jokers à borne inférieure » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Jokers à borne inférieure » ?

? super T pour les consommateurs Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Jokers à borne inférieure » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Jokers à borne supérieure
  2. Jokers à borne inférieure
  3. Principe PECS
  4. Jokers dans les API
← Retour à Java Academy