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
- Funzioni generiche e vincoli di tipo con where
- Varianza dichiarata nel punto di dichiarazione: in e out
- Star projection e quando usare *
- Type erasure e parametri di tipo reified