Tyyppien häviäminen ja reified-tyyppiparametrit
Käyttäkää reified-määrettä inline-funktioiden kanssa tyyppitietojen käyttämiseen ajon aikana.
Tyyppien häviäminen ja reified-tyyppiparametrit on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mikä on tyyppien häivytys?
Ajonaikana JVM häivyttää geneeristen tyyppien argumentit. List<String> ja List<Int> ovat molemmat vain List. Tämä rajoittaa geneerisiin tyyppeihin kohdistuvia tyyppioperaatioita ajonaikana.
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
}Ongelma: häivytettyjä tyyppejä ei voi tarkistaa
is-operaattoria ei voi käyttää tietyn geneerisen tyyppiargumentin kanssa, koska tyyppitieto on kadonnut ajonaikana.
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)
}inline-funktioiden kertaus
inline kopioi funktion rungon kutsukohtaan käännösaikana. Tämä mahdollistaa reified-määreen — myös tyyppiargumentti korvataan kutsukohdassa.
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: T:n käyttäminen ajonaikana
Kun yhdistät inline- ja reified-määreet, tyyppiargumentti säilyy kutsukohdassa, joten T:hen voi käyttää operaatioita is, as ja ::class.
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
}T:n KClass-arvon hakeminen
reified T-määreen avulla voit hakea arvon T::class ajonaikana — geneerisissä funktioissa tämä ei yleensä ole mahdollista.
inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
println(classNameOf<String>()) // String
println(classNameOf<Int>()) // Int
println(classNameOf<List<*>>()) // List
}Turvallinen muunnos reified-määreellä
Käytä reified-määrettä tyyppiturvallisen muunnosapuohjelman kirjoittamiseen niin, että se palauttaa null-arvon poikkeuksen heittämisen sijaan.
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
}JSON-jäsennys reified-määreellä
Gsonin ja kotlinx.serializationin kaltaiset kirjastot käyttävät reified-määrettä kohdetyypin päättelemiseen kutsukohdassa ilman, että Class-olioita tarvitsee välittää erikseen.
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 ja filterIsInstance
Standardikirjaston filterIsInstance<T>() käyttää reified-määrettä suodattaakseen listasta tietyn tyyppiset alkiot ilman manuaalisia tyyppimuunnoksia.
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]
}reified-määrettä ei voi käyttää ei-inline-funktioissa
reified toimii vain inline-funktioiden kanssa. Sen käyttäminen ilman inline-määrettä aiheuttaa käännösvirheen.
// 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 ja reflektio
Yhdistä reified-määre reflektioon, jotta voit tarkastella tyypin ominaisuuksia tai annotaatioita dynaamisesti ilman ylimääräisiä Class-parametreja.
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]
}Käytännössä: tyyppiturvallinen palvelupaikannin
Käytä reified-määrettä palvelupaikantimen rakentamiseen: se yhdistää KClass-arvot instansseihin ja mahdollistaa kevyen riippuvuuksien injektoinnin ilman annotaatioprosessoreita.
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!")
}reified-määreen rajoitukset
reified-tyyppiparametreja ei voi käyttää ei-inline-konteksteissa, tyyppiä ei voi tallentaa myöhempää käyttöä varten eikä sitä voi välittää ei-inline-funktioille, jotka tarvitsevat tyypin ajonaikana.
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>() }Pikatarkistus
Mitä tarvitaan, jotta tyyppiparametri voi olla reified?
Kertaus
Tyyppien häivytys poistaa geneeristen tyyppien tiedot ajonaikana. inline-funktioiden reified-määre säilyttää tyyppiargumentin kutsukohdassa ja mahdollistaa operaattorit is, as, ::class sekä T:hen kohdistuvan reflektion — ilman manuaalisesti välitettäviä Class-olioita.
Opi Kotlin tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”Tyyppien häviäminen ja reified-tyyppiparametrit” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “Tyyppien häviäminen ja reified-tyyppiparametrit”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Tyyppien häviäminen ja reified-tyyppiparametrit”?
Käyttäkää reified-määrettä inline-funktioiden kanssa tyyppitietojen käyttämiseen ajon aikana. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Tyyppien häviäminen ja reified-tyyppiparametrit”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?
Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Geneeriset funktiot ja tyyppirajoitteet wherella
- Deklaraatiopaikan varianssi: in ja out
- Star projection ja *-merkin käyttötarkoitus
- Tyyppien häviäminen ja reified-tyyppiparametrit