Il parametro Jolly – Lezione 28 di Java Avanzato

Il parametro Jolly “?”: il tipo sconosciuto

Il tipo jolly “?” viene utilizzato per offrire più funzionalità ai parametri di tipo e rappresenta in Java il cosiddetto “tipo sconosciuto“. Supponiamo di volere creare una lista generica, come potrebbe essere realizzata? List<Object> non potrà mai essere corretta perché List(qualcosa) non potrà mai essere suo sottotipo. Possiamo utilizzare i parametri di tipo, in questo caso una lista generica sarà così definita:

  List<T>

Utilizzando il parametro di tipo jolly avremo lo stesso risultato senza però introdurre i parametri di tipo. Si tratta di un notevole miglioramento! Una lista generica con il tipo jolly sarà definita nel seguente modo:

  List<?>

List<?> è la lista sottotipo comune a tutte le versioni di List. I vantaggi di utilizzare il parametro jolly sono tanti, ad esempio la versione parametrica del metodo size (che restituisce la dimensione della lista) è così definita:

  <T> int size (List<T> l) {
    return l.size();
  }

Come si può notare, il metodo non utilizza il parametro T. Per questo motivo viene introdotto un carico di lavoro inutile sia al sistema (cancellazione, ecc.) che all’utente che deve specificare il parametro di tipo. Con il parametro jolly, il metodo size risulta molto più semplice:

  int size (List<?> l) {
    return l.size();
  }

Ogni occorrenza di ? è a se stante, se ad esempio un metodo richiedesse gli elementi di due liste collegate tra loro non potremmo utilizzarle con in punti interrogativi perchè non hanno nessun legame tra loro. In questo caso bisogna utilizzare due parametri di tipo.

Una condizione importante nella relazione tra il tipo Jolly e i parametri di tipo è la seguente:

A<?> è supertipo di A<T>, per ogni T

Il parametro Jolly può essere usato solo come parametro attuale di tipo (nelle parentesi angolari), non è possibile dichiarare campi oppure nella creazione e nella dichiarazione di classi:

  //...
  ? var;
  new A<?>
  // ...
  class A<?> {
    // ...
  }

Le operazioni contenute nell’esempio sono tutte operazioni non valide in Java. Consentire questo tipo di operazioni significherebbe dire che tutti i metodi di un’ipotetica classe A<T> devono essere sostituiti tutti i parametri di tipo T con un punto interrogativo ?. Quest’affermazione nei metodi equivale a dire: dato che non conosco il tipo corretto che il metodo si aspetta (ho tutti i parametri come tipo sconosciuto ?), null è l’unico valore che è lecito passargli (andrà sempre bene).
Al contrario, in un metodo che restituisce i valori di tipo T, chiamandolo con A<?> l’unico valore a cui potremmo assegnare il valore restituito sarà di tipo Object. Si tratta dell’unico tipo che sicuramente accetta qualsiasi tipo sconosciuto (tranne i tipi base).

Il tipo jolly ? cerca di compensare le funzionalità dei parametri di tipo rispetto gli array in quanto non vengono introdotte nuove regole di sottotipi come per gli array.

Limiti superiori (extends) e inferiori (super) di Jolly

Come per i parametri di tipo, anche il parametro jolly è dotato di un limite superiore che in questo caso può essere solo uno:

  ? extends A

L’utilizzo della parola extends equivale a dire “tipo sconosciuto che estente (o implementa) A“. Viene detto limite superiore perché rappresenta tutte le sottoclassi che estendono A (con A inclusa). Ad esempio List<? extends Employee> è il supertipo comune a tutte le liste il cui parametro di tipo estente Employee.
Inoltre, a differenza dei parametri di tipo, il tipo jolly può avere anche un limite inferiore:

  ? super A

La parola super sta ad indicare “tipo sconosciuto che è superclasse di A“. Si tratta del limite inferiore del tipo jolly, ad esempio List<? super Employee> rappresenta una lista di tipo sconosciuto che è supertipo di Employee (ad esempio Person, Object, ecc.)

Bisogna prestare molta attenzione all’uso del tipo jolly, come abbiamo visto, soprattutto in presenza di limiti superiori o inferiori impongono determinate condizioni sulle chiamate ai metodi. Data la classe A<T> parametrica, la seguente tabella riassume le limitazioni che valgono per un riferimento di tipo A<?>, A<? extends B>, oppure A<? super B>, rispetto ad un metodo f(T) che accetta un argomento di tipo T, oppure ad un metodo T f() che restituisce un valore di tipo T.

Tipo del riferimento Cosa si può passare a f(T) Cosa si può assegnare a T f()
A<?> solo null solo ad Object
A<? extends B> solo null B e suoi supertipi
A<? super B> B e suoi sottotipi solo ad Object
 
Indice Lezione PrecedenteLezione Successiva

Pubblicato in Guide, Java, Programmazione Taggato con: , , , , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*