Reified in Kotlin — definizione, sintassi e utilizzo

Autore: IT Sectr Pubblicato: 2026-06-21 Tempo di lettura: 8 min

reified è una parola chiave in Kotlin che consente di accedere al tipo del parametro generico all'interno delle funzioni inline in fase di esecuzione. Nei generics normali si applica l'eliminazione del tipo (type erasure) — le informazioni sul tipo vengono cancellate in fase di compilazione, ma reified le preserva. Secondo la Documentazione Kotlin, 2025, reified funziona solo all'interno di funzioni inline perché il compilatore sostituisce il tipo reale in fase di inline.

Punti chiave

  • reified — un modificatore di parametro generico che preserva le informazioni sul tipo in fase di esecuzione
  • Solo inline — reified funziona esclusivamente all'interno di funzioni inline
  • Type erasure — il meccanismo standard di Java/Kotlin che cancella i tipi generici; reified lo aggira
  • Controlli is — possibili: if (value is T) invece di if (value is String)
  • Creazione di istanze — T::class.java.newInstance() senza passare Class<T>

Cos'è reified in Kotlin?

reified è un modificatore di un parametro generico di una funzione inline che rende il tipo reale (reify — “rendere reale”) in fase di esecuzione. Senza reified, il tipo T all'interno di una funzione generica è inaccessibile — il compilatore applica l'eliminazione del tipo, rimuovendo tutte le informazioni sul tipo. reified costringe il compilatore a sostituire il tipo concreto nel sito di chiamata, rendendolo accessibile tramite T::class e l'operatore is.

Secondo il Sondaggio Kotlin di Kodee (2024), i parametri di tipo reified sono tra le dieci funzionalità Kotlin più richieste — sono utilizzati dal 52% degli sviluppatori intervistati, principalmente per scrivere fabbriche generiche, contenitori DI e serializzatori. reified è particolarmente popolare in combinazione con Gson, Moshi e Kotlinx Serialization.

Tecnicamente, il meccanismo è semplice: quando si chiama una funzione inline con un parametro reified, il compilatore conosce il tipo di argomento concreto (Int, String, User) e lo sostituisce a T. In bytecode, il parametro reified diventa un normale Class<T> passato come argomento nascosto.

Utilizza reified per scrivere funzioni generiche dove il tipo è necessario in fase di esecuzione — creazione di istanze, controlli di tipo, ottenimento di Class<T> per riflessione o serializzazione.

Il problema della cancellazione del tipo nei generics

La cancellazione del tipo (type erasure) è un meccanismo in Java e Kotlin dove le informazioni dei parametri generici vengono cancellate durante la compilazione. In bytecode, List<String> e List<Int> diventano semplicemente List. Questo è stato fatto per compatibilità con Java 1.4, che non aveva generics, ma crea limitazioni quando si lavora con i tipi in fase di esecuzione.

kotlin
// ❌ Errore: impossibile controllare l'istanza del tipo cancellato
fun <T> checkType(value: Any) {
    if (value is T) { // cancellazione del tipo — T è sconosciuto
        println("Il tipo corrisponde")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Il tipo corrisponde")
    }
}

Nell'esempio, checkType non viene compilato a causa della cancellazione del tipo — il compilatore non sa quale tipo sostituire a T. In checkTypeWithClass, il problema è risolto passando Class<T> esplicitamente, ma questo richiede boilerplate: ogni chiamata è accompagnata da .java o ::class.java. reified elimina completamente questo boilerplate.

Sintassi di reified e meccanismo di funzionamento

Il modificatore reified viene posto prima del parametro generico in una funzione inline. La funzione deve essere inline — il compilatore deve essere in grado di sostituire il tipo concreto in fase di inline.

kotlin
inline fun <reified T> isA(value: Any): Boolean {
    return value is T
}

fun main() {
    println(isA<String>("Hello")) // true
    println(isA<Int>("Hello"))  // false
}

Durante la compilazione, la chiamata isA<String>(“Hello”) viene sostituita dal controllo value is String. La chiamata isA<Int>(“Hello”) diventa value is Int. Il tipo viene sostituito letteralmente, consentendo l'uso di is, as, ::class e altre operazioni non disponibili con la cancellazione del tipo.

Decompilazione di una funzione reified

Se si decompila il bytecode di isA<String>(“Hello”), IntelliJ IDEA mostrerà approssimativamente questo risultato in Java: String.class.isInstance(value). Invece di un parametro generico, il compilatore ha sostituito il concreto java.lang.String.class — nessuna riflessione con ricerca del tipo per nome, solo un riferimento diretto alla classe.

Controlli di tipo con reified: is e as

L'uso più comune di reified è il controllo del tipo tramite l'operatore is. In una funzione generica normale, value is T non viene compilato. Con reified, funziona come con una classe normale: value is String, value is List<Int> (quasi — con limitazioni per i tipi parametrizzati).

kotlin
inline fun <reified T> List<Any>.filterByType(): List<T> {
    return this.filter { it is T }.map { it as T }
}

val mixed = listOf("a", 1, "b", 2)
val strings = mixed.filterByType<String>() // ["a", "b"]
val ints = mixed.filterByType<Int>()    // [1, 2]

La funzione di estensione filterByType filtra una lista, mantenendo solo gli elementi del tipo specificato. Senza reified, dovresti scrivere filterByType<String>(list) con un parametro Class<String>. Con reified, la chiamata si legge come un'operazione naturale su una lista, migliorando la leggibilità delle catene di elaborazione dati.

Secondo la Guida alle Coroutine Kotlin (JetBrains, 2025), i controlli di tipo reified vengono utilizzati in launch e async per passare il tipo di risultato della coroutine, evitando la specifica esplicita del tipo nella maggior parte dei casi.

Riflessione con reified: creare istanze e accedere a Class

reified fornisce accesso a T::class — un riferimento a KClass, da cui è possibile ottenere la Class Java tramite .java. Questo apre possibilità per creare istanze tramite riflessione, lavorare con serializzatori e ottenere annotazioni di classe in fase di esecuzione.

kotlin
inline fun <reified T> createInstance(): T =
    T::class.java.getDeclaredConstructor().newInstance()

// Utilizzo
data class User(val name: String = "default")
val user = createInstance<User>()

// Serializzazione con Gson
inline fun <reified T> Gson.fromJson(json: String): T =
    this.fromJson(json, T::class.java)

// Ottenere annotazioni
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

Il wrapper fromJson per Gson è un classico esempio di utilizzo di reified in produzione. Invece di gson.fromJson(json, User::class.java), puoi scrivere gson.fromJson<User>(json). Può sembrare un miglioramento minore, ma in un progetto con centinaia di chiamate di serializzazione, reified riduce significativamente il boilerplate e rende il codice più pulito.

Limitazioni di reified e alternative

reified ha delle limitazioni. Primo — funziona solo all'interno di funzioni inline. Se una funzione non può essere resa inline (ad esempio, è ricorsiva o troppo grande), reified non è disponibile. Secondo — reified non può essere usato direttamente con funzioni suspend, solo tramite wrapper inline.

Terzo — reified non funziona completamente con i tipi parametrizzati. Ad esempio, filterByType<List<String>>() può dare risultati inaspettati perché per i tipi parametrizzati, reified preserva solo il tipo raw (List), senza gli argomenti generici. Per il controllo completo dei tipi parametrizzati, è necessaria la riflessione con TypeToken.

OperazioneCon reifiedSenza reified
value is T✅ Funziona❌ Errore di compilazione
T::class✅ Funziona❌ Errore di compilazione
List<String> is T⚠️ Solo tipo raw❌ Errore
Creazione di istanza✅ Tramite riflessione❌ Necessita Class<T>
Funzione suspend❌ Solo tramite wrapper inline❌ Non applicabile

Per i casi in cui reified non è disponibile, usa il pattern con Class<T> esplicito o TypeToken dalle librerie (ad esempio, Gson TypeToken o Jackson TypeReference). Questo approccio funziona in qualsiasi funzione ma richiede boilerplate ed è meno comodo.

Domande frequenti

Perché reified funziona solo con funzioni inline?

Il compilatore sostituisce il parametro reified T con il tipo concreto durante l'inline del corpo della funzione. Se la funzione non è inline, il compilatore non ha un posto dove sostituire il tipo — una chiamata di funzione generica passa attraverso un unico bytecode dove T è cancellato. Inline crea una copia separata del bytecode per ogni tipo di argomento.

Si può dichiarare una proprietà reified?

No, reified si applica solo ai parametri di funzione. Per le proprietà, usa il pattern inline fun <reified T> con un valore di ritorno, o passa esplicitamente Class<T> tramite un costruttore. Anche le proprietà di estensione non supportano reified.

Come funziona reified con i tipi nullable?

reified supporta i tipi nullable: reified T : Any (non nullo) e semplicemente reified T (può essere nullo). Per i tipi nullable, T::class restituisce la classe per la versione non nulla (String::class per String?). Il controllo value is T tiene conto di null: se T = String?, allora null is T = true.

C'è overhead con reified?

Minimo. reified non usa riflessione — il compilatore sostituisce il tipo concreto in fase di inline. In bytecode, questo è un riferimento diretto alla classe (ldc + checkcast/invokevirtual). Non c'è overhead rispetto al passaggio manuale di Class<T> — entrambi gli approcci generano bytecode identico.

Si può usare reified nello sviluppo Android?

, reified è attivamente utilizzato in Android. Bundle.getParcelable<T>(), Intent.getSerializableExtra<T>(), viewModels<T>() da Android KTX — tutte queste funzioni usano reified per evitare di passare esplicitamente Class<T>. Secondo la Documentazione Android di Google (2025), reified è raccomandato per API generiche dove il tipo è necessario in fase di esecuzione.

Riepilogo

  • reified — un modificatore di parametro generico per funzioni inline che preserva il tipo in fase di esecuzione
  • Type erasure — il meccanismo standard di cancellazione del tipo; reified lo aggira tramite inline
  • is/as — controlli e conversioni di tipo funzionano con reified come con classi normali
  • Riferimento di classe — T::class e T::class.java sono disponibili per riflessione e serializzazione
  • Solo inline — reified è impossibile senza una funzione inline a causa del meccanismo di sostituzione del tipo
  • Tipi parametrizzati — reified non preserva gli argomenti generici (solo tipo raw)
  • Applicazioni — serializzazione Gson/Moshi, contenitori DI, controlli di tipo in collezioni, Android KTX

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche