Proyección estrella y cuándo usar *
Aplique la proyección estrella a tipos genéricos desconocidos y comprenda sus límites.
Proyección estrella y cuándo usar * es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.
¿Qué es la proyección de estrella?
La proyección de estrella (*) es la forma que tiene Kotlin de expresar «un tipo genérico con un argumento de tipo desconocido». Es el equivalente seguro del tipo sin formato o del comodín sin límite <?> de Java.
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"))
}Lectura desde tipos con proyección de estrella
Desde un List<*> puede leer los elementos como Any?. No puede añadir elementos porque se desconoce el tipo real.
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))
}Estrella frente a out Any
List<*> y List<out Any?> son equivalentes. La proyección de estrella es una forma abreviada de la proyección covariante con el límite superior.
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
}Estrella en los parámetros de función
Use * en las firmas de funciones cuando necesite aceptar cualquier variante genérica, pero solo llamar a métodos que no requieran conocer T.
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))
}Estrella con MutableList
Para MutableList<*>, puede leer como Any?, pero no puede escribir en absoluto; el compilador lo impide.
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]
}Clase con proyección de estrella
Al comprobar en tiempo de ejecución el tipo de una clase genérica, use la proyección de estrella porque los argumentos de tipo se borran.
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
}Varios parámetros con proyección de estrella
Una función puede tener varios parámetros con proyección de estrella al trabajar con pares o mapas de tipos desconocidos.
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))
}Cuándo NO usar la estrella
Evite la proyección de estrella cuando necesite escribir en una colección o cuando pueda usar en su lugar un parámetro de tipo acotado; el tipo acotado proporciona más información.
// 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)
}Estrella con comprobaciones y conversiones de tipos
Use la proyección de estrella para realizar comprobaciones instanceof en clases genéricas y, después, convertir al tipo específico para trabajar con él.
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)
}Práctica: despachador genérico de eventos
Un despachador que acepta cualquier Handler<*>, pero distribuye eventos con tipos de forma segura.
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)
}Estrella en contextos reificados
La proyección de estrella es especialmente común en código de reflexión y serialización, donde el tipo en tiempo de ejecución se inspecciona mediante KClass<*>.
fun printClassName(klass: kotlin.reflect.KClass<*>) {
println(klass.simpleName)
}
fun main() {
printClassName(String::class) // String
printClassName(List::class) // List
printClassName(Int::class) // Int
}Comprobación rápida
¿Qué tipo obtiene al leer de un List<*>?
Resumen
La proyección de estrella (*) acepta cualquier variante genérica para el acceso de solo lectura. Úsela para comprobaciones de tipos, utilidades genéricas y reflexión. Evítela cuando necesite escribir en una colección o cuando un parámetro de tipo acotado proporcione una mejor seguridad de tipos.
Preguntas frecuentes
¿La lección «Proyección estrella y cuándo usar *» es gratis?
Sí — el texto completo de «Proyección estrella y cuándo usar *» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Proyección estrella y cuándo usar *»?
Aplique la proyección estrella a tipos genéricos desconocidos y comprenda sus límites. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Kotlin Academy?
No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Proyección estrella y cuándo usar *»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?
Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Funciones genéricas y restricciones de tipos con where
- Varianza en el sitio de declaración: in y out
- Proyección estrella y cuándo usar *
- Borrado de tipos y parámetros de tipo reified