0Pricing
Java Academy · Lezione

Wildcard con limite inferiore

? super T per i consumatori

Wildcard con limite inferiore è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

La wildcard con limite inferiore

? super T è una wildcard con limite inferiore. Indica "un tipo sconosciuto che è T o un suo supertipo".

List<? super Integer> può riferirsi a una List<Integer>, a una List<Number> oppure a una 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);
    }
}

Scrivere in un consumatore

Con ? super Integer è possibile aggiungere in sicurezza qualsiasi Integer (o sottotipo di Integer).

Qualunque sia il tipo reale della lista, essa è almeno una lista di un supertipo di Integer, quindi un Integer è sempre compatibile.

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 lettura restituisce Object

Il compromesso è il seguente: quando legge da una lista ? super T, il compilatore sa soltanto che gli elementi sono di un supertipo sconosciuto di T.

L'unico tipo sicuro per la lettura è 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);
    }
}

Perché la lettura è limitata

Una List<? super Integer> potrebbe essere in realtà una List<Object> che contiene stringhe.

Una lettura potrebbe quindi restituire qualsiasi Object. Il compilatore non può garantire che si tratti di un Integer, perciò le letture restituiscono solo Object.

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());
    }
}

Caso d'uso del consumatore

Utilizzi ? super T quando un metodo si limita a consumare valori, cioè a scriverli.

Un metodo che riempie una raccolta di destinazione è il caso classico.

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);
    }
}

Anche l'aggiunta dei sottotipi funziona

Con ? super Number è possibile aggiungere qualsiasi Number o un suo sottotipo: Integer, Double, Long.

Il limite inferiore garantisce che la lista accetti almeno Number, quindi tutti i sottotipi sono compatibili.

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);
    }
}

Stile Collections.addAll

Il JDK usa i limiti inferiori per i contenitori di destinazione. Ad esempio, un metodo generico che inserisce elementi in una destinazione.

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);
    }
}

Comparator con super

Un esempio pratico: Comparator<? super T> consente a un ordinamento di accettare un comparatore scritto per un supertipo.

Un comparatore che confronta qualsiasi Object tramite toString può ordinare una lista di String.

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);
    }
}

super ed extends sono speculari

Le due wildcard sono opposte:

  • ? extends T: legge T, non può scrivere. È un produttore.
  • ? super T: scrive T, legge solo Object. È un consumatore.

Questa simmetria è il cuore della regola PECS che imparerà tra poco.

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);
    }
}

Copiare tra limiti diversi

Un metodo di copia mostra entrambe le wildcard contemporaneamente: legge da ? extends T e scrive in ? 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);
    }
}

Quando non usare una wildcard

Se un metodo legge e scrive T, non utilizzi una wildcard. Usi invece un tipo esatto o un parametro di tipo con nome.

Le wildcard esistono precisamente per i casi di sola lettura o sola scrittura.

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);
    }
}

Verifica rapida

Verifichi la Sua comprensione dei limiti inferiori.

Riepilogo

Ha imparato a usare le wildcard con limite inferiore:

  • ? super T indica un supertipo sconosciuto di T.
  • È possibile scrivere T e i suoi sottotipi (un consumatore).
  • Le letture restituiscono solo Object.
  • È l'immagine speculare esatta di ? extends T.

Ora vediamo la regola che riunisce entrambi i concetti: 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);
    }
}

Domande Frequenti

La lezione «Wildcard con limite inferiore» è gratuita?

Sì — il testo completo di «Wildcard con limite inferiore» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Wildcard con limite inferiore»?

? super T per i consumatori Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Wildcard con limite inferiore»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Wildcard con limite superiore
  2. Wildcard con limite inferiore
  3. Il principio PECS
  4. Wildcard nelle API
← Torna a Java Academy