0Pricing
Kotlin Academy · Lezione

Type erasure e parametri di tipo reified

Utilizzi reified con le funzioni inline per accedere alle informazioni sui tipi a runtime.

Type erasure e parametri di tipo reified è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 4 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 Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Cos'è la type erasure?

A runtime, la JVM cancella gli argomenti di tipo generico. List<String> e List<Int> sono entrambe semplicemente List. Questo limita le operazioni sui tipi generici a runtime.

fun main() {
    val strings: List<String> = listOf("a", "b")
    val ints: List<Int> = listOf(1, 2)
    println(strings.javaClass == ints.javaClass) // true: both ArrayList
    println(strings is List<*>)  // OK with star
    // println(strings is List<String>) // warning: unchecked cast
}

Il problema: impossibile controllare i tipi cancellati

Non è possibile usare is con uno specifico argomento di tipo generico, perché le informazioni sul tipo vengono perse a runtime.

fun checkType(obj: Any) {
    // This works:
    if (obj is List<*>) println("It's a list of something")
    // This doesn't compile cleanly:
    // if (obj is List<String>) println("It's a list of strings") // unchecked
}
fun main() {
    checkType(listOf("hello"))
    checkType(42)
}

Riepilogo delle funzioni inline

inline copia il corpo della funzione nel punto di chiamata durante la compilazione. Questo abilita reified: anche l'argomento di tipo viene sostituito nel punto di chiamata.

inline fun <T> myRun(block: () -> T): T = block()
fun main() {
    val result = myRun { 42 }
    println(result) // 42
    // The compiler inlines the lambda body — no object allocation
}

reified: accesso a T a runtime

La combinazione di inline e reified conserva l'argomento di tipo nel punto di chiamata, consentendo di usare is, as e ::class su T.

inline fun <reified T> isInstance(value: Any): Boolean = value is T
fun main() {
    println(isInstance<String>("hello"))  // true
    println(isInstance<Int>("hello"))     // false
    println(isInstance<List<*>>(listOf())) // true
}

Ottenere la KClass di T

Con reified T è possibile ottenere T::class a runtime, cosa normalmente impossibile nelle funzioni generiche.

inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
    println(classNameOf<String>())   // String
    println(classNameOf<Int>())      // Int
    println(classNameOf<List<*>>())  // List
}

Cast sicuro con reified

Utilizzi reified per scrivere un'utility di cast type-safe che restituisca null invece di generare un'eccezione.

inline fun <reified T> Any?.safeCast(): T? = this as? T
fun main() {
    val obj: Any = "Hello"
    val s: String? = obj.safeCast<String>()
    val i: Int? = obj.safeCast<Int>()
    println(s) // Hello
    println(i) // null
}

Parsing JSON con reified

Librerie come Gson o kotlinx.serialization utilizzano reified per inferire il tipo di destinazione nel punto di chiamata, senza passare esplicitamente oggetti Class.

import com.google.gson.Gson
// Simulated without real Gson:
inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java)
}
// Usage:
// val user: User = parseJson<User>("""{"name":"Alice"}""")

reified con filterIsInstance

La filterIsInstance<T>() della libreria standard utilizza reified per filtrare una lista in base a un tipo specifico, senza cast manuali.

fun main() {
    val mixed: List<Any> = listOf(1, "hello", 2.5, "world", true)
    val strings = mixed.filterIsInstance<String>()
    val ints = mixed.filterIsInstance<Int>()
    println(strings) // [hello, world]
    println(ints)    // [1]
}

Impossibile usare reified nelle funzioni non inline

reified funziona soltanto con funzioni inline. Tentare di usarlo senza inline genera un errore di compilazione.

// Error:
// fun <reified T> broken(): String = T::class.simpleName ?: "?"

// Must be inline:
inline fun <reified T> correct(): String = T::class.simpleName ?: "?"
fun main() {
    println(correct<Double>()) // Double
}

reified e reflection

Combini reified con la reflection per ispezionare dinamicamente proprietà o annotazioni di un tipo, senza i parametri Class ripetitivi.

inline fun <reified T : Any> properties(): List<String> =
    T::class.members.map { it.name }
data class Point(val x: Int, val y: Int)
fun main() {
    println(properties<Point>()) // [x, y, component1, component2, copy, equals, hashCode, toString]
}

Pratica: service locator type-safe

Utilizzi reified per creare un service locator che associ KClass alle istanze, ottenendo una DI leggera senza annotation processor.

val registry = mutableMapOf<kotlin.reflect.KClass<*>, Any>()
inline fun <reified T : Any> register(instance: T) { registry[T::class] = instance }
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> resolve(): T = registry[T::class] as T
class Logger { fun log(msg: String) = println("[LOG] $msg") }
fun main() {
    register(Logger())
    resolve<Logger>().log("Service located!")
}

Limitazioni di reified

I parametri di tipo reified non possono essere utilizzati in contesti non inline, non possono memorizzare il tipo per un uso successivo e non possono essere passati a funzioni non inline che richiedono il tipo a runtime.

inline fun <reified T> foo() {
    val clazz = T::class // OK here
    // bar(clazz)        // must pass clazz explicitly to non-inline funs
    println(clazz.simpleName)
}
fun bar(clazz: kotlin.reflect.KClass<*>) = println(clazz.simpleName)
fun main() { foo<String>() }

Verifica rapida

Cosa è necessario perché un parametro di tipo sia reified?

Riepilogo

La type erasure rimuove le informazioni sui tipi generici a runtime. reified nelle funzioni inline conserva l'argomento di tipo nel punto di chiamata, consentendo is, as, ::class e la reflection su T, senza passare manualmente oggetti Class.

Domande Frequenti

La lezione «Type erasure e parametri di tipo reified» è gratuita?

Sì — il testo completo di «Type erasure e parametri di tipo reified» è 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 Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «Type erasure e parametri di tipo reified»?

Utilizzi reified con le funzioni inline per accedere alle informazioni sui tipi a runtime. Eserciti Kotlin 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 Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin 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 4 di 4.

Quanto tempo richiede la lezione «Type erasure e parametri di tipo reified»?

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 Kotlin Academy?

Sì. Ogni lezione Kotlin 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. Funzioni generiche e vincoli di tipo con where
  2. Varianza dichiarata nel punto di dichiarazione: in e out
  3. Star projection e quando usare *
  4. Type erasure e parametri di tipo reified
← Torna a Kotlin Academy