Projeção estrela e quando usar *
Aplique a projeção estrela a tipos genéricos desconhecidos e entenda suas limitações.
Projeção estrela e quando usar * é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O que é a projeção estrela?
A projeção estrela (*) é a forma do Kotlin de dizer "um tipo genérico com um argumento de tipo desconhecido". Ela é o equivalente seguro do tipo bruto do Java ou do curinga sem limite <?>.
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"))
}Leitura de tipos com projeção estrela
A partir de uma List<*>, você pode ler os elementos como Any?. Não é possível adicionar elementos porque o tipo real é desconhecido.
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))
}Projeção estrela versus out Any
List<*> e List<out Any?> são equivalentes. A projeção estrela é uma forma abreviada da projeção covariante com o limite 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
}Projeção estrela nos parâmetros de funções
Use * nas assinaturas de funções quando precisar aceitar qualquer variante genérica, mas só chamar métodos que não exijam conhecer 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))
}Projeção estrela com MutableList
Para MutableList<*>, você pode ler como Any?, mas não pode escrever de forma alguma — o compilador impede isso.
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]
}Classe com projeção estrela
Ao verificar em tempo de execução o tipo de uma classe genérica, use a projeção estrela porque os argumentos de tipo são apagados.
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
}Vários parâmetros com projeção estrela
Uma função pode ter vários parâmetros com projeção estrela ao trabalhar com pares ou mapas de tipos desconhecidos.
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))
}Quando NOT usar a projeção estrela
Evite a projeção estrela quando precisar escrever em uma coleção ou quando puder usar um parâmetro de tipo limitado — o tipo limitado fornece mais informações.
// 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)
}Projeção estrela com verificações de tipo e conversões
Use a projeção estrela para realizar verificações instanceof em classes genéricas e depois converter para um tipo específico para o trabalho efetivo.
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ática: distribuidor genérico de eventos
Um distribuidor que aceita qualquer Handler<*>, mas distribui eventos tipados com segurança.
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)
}Projeção estrela em contextos reificados
A projeção estrela é especialmente comum em código de reflexão e serialização, no qual o tipo em tempo de execução é inspecionado por meio de KClass<*>.
fun printClassName(klass: kotlin.reflect.KClass<*>) {
println(klass.simpleName)
}
fun main() {
printClassName(String::class) // String
printClassName(List::class) // List
printClassName(Int::class) // Int
}Verificação rápida
Que tipo você obtém ao ler de uma List<*>?
Revisão
A projeção estrela (*) aceita qualquer variante genérica para acesso somente de leitura. Use-a para verificações de tipo, utilitários genéricos e reflexão. Evite-a quando precisar escrever em uma coleção ou quando um parâmetro de tipo limitado oferecer mais segurança de tipos.
Perguntas Frequentes
A aula “Projeção estrela e quando usar *” é grátis?
Sim — o texto completo de “Projeção estrela e quando usar *” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “Projeção estrela e quando usar *”?
Aplique a projeção estrela a tipos genéricos desconhecidos e entenda suas limitações. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Projeção estrela e quando usar *”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Funções genéricas e restrições de tipos com where
- Variância no local da declaração: in e out
- Projeção estrela e quando usar *
- Apagamento de tipos e parâmetros de tipo reified