Stjerneprojeksjon og når * bør brukes
Bruk stjerneprojeksjon for ukjente generiske typer, og forstå begrensningene.
Stjerneprojeksjon og når * bør brukes er en gratis leksjon i Kotlin Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Kotlin Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Kotlin Academy inneholder totalt 4 leksjoner.
Hva er stjerneprojeksjon?
Stjerneprojeksjon (*) er Kotlins måte å uttrykke «en generisk type med et ukjent typeargument» på. Det er det typesikre motstykket til Javas råtype eller ubundne jokertegn <?>.
fun printList(list: List<*>) {
for (item in list) println(item)
}
fun main() {
printList(listOf(1, 2, 3))
printList(listOf("a", "b"))
printList(listOf(true, 42, "mixed"))
}Lese fra stjerneprojiserte typer
Fra en List<*> kan De lese elementer som Any?. De kan ikke legge til elementer fordi den faktiske typen er ukjent.
fun process(list: List<*>) {
val first: Any? = list.firstOrNull()
println("First: $first, Size: ${list.size}")
// list.add("x") // compile error: can't write to List<*>
}
fun main() {
process(listOf(10, 20, 30))
}Stjerne kontra out Any
List<*> og List<out Any?> er ekvivalente. Stjerneprojeksjon er en kortform for den kovariante projeksjonen med den øvre grensen.
fun sumStars(list: List<*>): Int = list.size
fun sumOut(list: List<out Any?>): Int = list.size
fun main() {
val l = listOf(1, "two", true)
println(sumStars(l)) // 3
println(sumOut(l)) // 3
}Stjerne i funksjonsparametere
Bruk * i funksjonssignaturer når De må ta imot en hvilken som helst generisk variant, men bare kalle metoder som ikke krever at T er kjent.
fun containerInfo(map: Map<*, *>): String {
return "keys=${map.keys.size}, values=${map.values.size}"
}
fun main() {
val m = mapOf(1 to "one", 2 to "two")
println(containerInfo(m))
}Stjerne med MutableList
For MutableList<*> kan De lese som Any?, men ikke skrive i det hele tatt – kompilatoren forhindrer dette.
fun clearFirstElement(list: MutableList<*>) {
if (list.isNotEmpty()) {
list.removeAt(0) // OK: remove by index doesn't need T
// list.add("x") // Error: can't write unknown type
}
}
fun main() {
val m = mutableListOf(1, 2, 3)
clearFirstElement(m)
println(m) // [2, 3]
}Klasse med stjerneprojeksjon
Når De kontrollerer en generisk klassetype ved kjøretid, bør De bruke stjerneprojeksjon fordi typeargumenter fjernes.
fun isListOfSomething(obj: Any): Boolean {
return obj is List<*> // OK with star
// obj is List<String> // Warning: cannot check erased type
}
fun main() {
println(isListOfSomething(listOf(1, 2))) // true
println(isListOfSomething("not a list")) // false
}Flere stjerneparametere
En funksjon kan ha flere stjerneprojiserte parametere når den arbeider med par eller map-er med ukjente typer.
fun describeMap(map: Map<*, *>) {
map.forEach { (k, v) ->
println("${k?.javaClass?.simpleName} -> ${v?.javaClass?.simpleName}")
}
}
fun main() {
describeMap(mapOf("key" to 42, 1 to true))
}Når stjerne IKKE bør brukes
Unngå stjerneprojeksjon når De må skrive til en samling, eller når De kan bruke en begrenset typeparameter i stedet – en begrenset typeparameter gir mer informasjon.
// Bad: loses type information
fun addToStar(list: MutableList<*>, item: Any?) {
// list.add(item) // compile error
}
// Better: use bounded type parameter
fun <T : Any> addTyped(list: MutableList<T>, item: T) {
list.add(item)
}
fun main() {
val l = mutableListOf("a")
addTyped(l, "b")
println(l)
}Stjerne med typesjekker og casts
Bruk stjerneprojeksjon til å utføre instanceof-sjekker på generiske klasser, og cast deretter til en bestemt type for det faktiske arbeidet.
fun handleResponse(response: Any) {
if (response is List<*>) {
val list = response as List<*>
println("List with ${list.size} elements")
val first = list.firstOrNull()
if (first is String) println("First string: $first")
}
}
fun main() {
handleResponse(listOf("hello", "world"))
handleResponse(42)
}Praktisk: Generisk hendelsesdispatcher
En dispatcher som tar imot en hvilken som helst Handler<*>, men dispatcher typesikre hendelser.
interface Handler<in T> { fun handle(event: T) }
class LogHandler : Handler<Any> {
override fun handle(event: Any) = println("Event: $event")
}
fun dispatch(handler: Handler<*>, event: Any) {
@Suppress("UNCHECKED_CAST")
(handler as Handler<Any>).handle(event)
}
fun main() {
dispatch(LogHandler(), "click")
dispatch(LogHandler(), 42)
}Stjerne i reified-kontekster
Stjerneprojeksjon er spesielt vanlig i refleksjons- og serialiseringskode, der kjøretidstypen inspiseres via KClass<*>.
fun printClassName(klass: kotlin.reflect.KClass<*>) {
println(klass.simpleName)
}
fun main() {
printClassName(String::class) // String
printClassName(List::class) // List
printClassName(Int::class) // Int
}Kort kontroll
Hvilken type får De når De leser fra en List<*>?
Oppsummering
Stjerneprojeksjon (*) godtar alle generiske varianter for skrivebeskyttet tilgang. Bruk den til typesjekker, generiske verktøy og refleksjon. Unngå den når De må skrive til en samling, eller når en begrenset typeparameter gir bedre typesikkerhet.
Lær deg Kotlin med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 51
- Leksjoner
- 203
Ofte stilte spørsmål
Er leksjonen «Stjerneprojeksjon og når * bør brukes» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Kotlin Academy, inkludert «Stjerneprojeksjon og når * bør brukes», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Kotlin Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Stjerneprojeksjon og når * bør brukes»?
Bruk stjerneprojeksjon for ukjente generiske typer, og forstå begrensningene. Du øver på Kotlin Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Kotlin Academy?
Ingen tidligere erfaring er nødvendig. Kotlin Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Stjerneprojeksjon og når * bør brukes»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Kotlin Academy-leksjonen?
Ja. Alle Kotlin Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Generiske funksjoner og typebegrensninger med where
- Varians på deklarasjonsstedet: in og out
- Stjerneprojeksjon og når * bør brukes
- Typeutvisking og reified-typeparametere