ProgrammazioneBackend Developer

Che cos'è il pattern matching in Java, a che fase di implementazione è, a cosa serve e quali sono le sfumature da conoscere? Fai un esempio.

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della questione

Il pattern matching è una tecnica, presa in prestito da linguaggi funzionali e di scripting, che consente di controllare il tipo e estrarre dati in un solo passaggio. In Java, lo sviluppo del pattern matching è iniziato con Java 14 (funzione in anteprima), è migliorato con Java 16-17 e, nelle ultime versioni, si sta espandendo anche nello switch.

Problema

Il modo classico di controllare il tipo e fare il cast sembrava ingombrante:

if (obj instanceof String) { String s = (String) obj; ... }

Comparivano variabili non necessarie, una grande quantità di codice boilerplate e il rischio di errori di casting dei tipi.

Soluzione

Il pattern matching consente di combinare il controllo del tipo, la dichiarazione di una nuova variabile e il suo utilizzo in un'unica espressione:

if (obj instanceof String s) { System.out.println(s.length()); }

Pattern simili stanno ora apparendo nella costruzione switch, rendendo il codice più conciso e meno soggetto a errori.

Caratteristiche chiave:

  • Lavoro conciso e sicuro con i tipi.
  • Riduzione degli errori nei cast.
  • Facilità di manutenzione del codice e di estensione a nuovi tipi.

Domande ad inganno.

Si può usare il pattern matching per classi personalizzate o solo per tipi standard?

Può essere usato per qualsiasi classe. Il pattern matching funziona per tutte le classi su cui si può applicare instanceof.

La variabile del pattern sarà accessibile al di fuori del blocco if/switch?

No, la variabile dichiarata all'interno del pattern matching è visibile solo all'interno di quel blocco in cui è stata creata (ad esempio, all'interno di un if o di un case switch).

Esempio di codice:

if (obj instanceof Integer i) { // i è visibile solo in questo blocco System.out.println(i + 10); } // Qui i non è accessibile

Si può usare il pattern matching con i generics?

Sì, in questo modo:

Object list = List.of("a", "b"); if (list instanceof List<?> l) { System.out.println(l.size()); }

Tuttavia, lavorare con tipi raw e fare il cast a tipi parametrizzati è ancora limitato a causa del type erasure.

Errori tipici e anti-pattern

  • Supporre che il pattern matching gestisca automaticamente i null: se l'oggetto è uguale a null, la condizione non verrà soddisfatta (instanceof con null è sempre false).
  • Utilizzare il pattern matching dove è sufficiente il metodo getClass().
  • L'uso eccessivo del pattern matching può peggiorare l'architettura, se le intenzioni non sono chiare.

Esempio dalla vita reale

Caso negativo

Il team ha implementato il pattern matching in tutti i casi, inclusi DTO interni, classi di servizio e situazioni in cui il polimorfismo era sufficiente. Il codice è diventato troppo dipendente da instanceof, il ruolo delle gerarchie di classi è stato offuscato.

Vantaggi:

  • Implementazione rapida.
  • Stile conciso.

Svantaggi:

  • Errori architetturali.
  • Minore leggibilità.

Caso positivo

Nel progetto, il pattern matching è stato applicato solo per interfacce generiche, utilità ausiliarie e gestione di collezioni di tipo sconosciuto. L'architettura OOP è rimasta intatta, l'uso del pattern è avvenuto solo dove era davvero necessario.

Vantaggi:

  • Codice leggibile.
  • Supporto all'architettura.

Svantaggi:

  • Richiede progettazione attenta e conoscenza della versione JDK.