Como passar em uma entrevista de Kotlin: principais perguntas de nível avançado
A entrevista para a posição de Desenvolvedor Kotlin Sênior não é apenas uma verificação de sintaxe. Os entrevistadores querem ver um profundo entendimento da arquitetura da linguagem, características de compilação e concorrência. Neste artigo, analisaremos as perguntas mais difíceis e frequentes que ajudarão você a passar com confiança na entrevista técnica. O material é voltado para desenvolvedores que já têm experiência com Kotlin e Java.
1. Corrotinas: Structured Concurrency e cancelamento de tarefas
Corrotinas são um dos pontos fortes do Kotlin. Uma pergunta avançada frequentemente aborda Structured Concurrency. O entrevistador pode perguntar: "O que acontece se uma corrotina filha lançar uma exceção e a corrotina pai não a capturar?"
A resposta está na hierarquia de Job. Se uma corrotina filha (iniciada via coroutineScope ou dentro de launch) falhar com uma exceção, ela se propaga para o pai. A corrotina pai é cancelada, e todas as suas tarefas filhas também. Isso torna o código previsível e seguro.
Exemplo que vale a pena mostrar na entrevista:
import kotlinx.coroutines.*
fun main() = runBlocking { try { coroutineScope { launch { delay(100) throw RuntimeException("Erro na corrotina filha") } launch { delay(200) println("Esta corrotina não será executada se a primeira falhar") } } } catch (e: Exception) { println("Exceção capturada: ${e.message}") } println("O programa continua em execução")}Outra pergunta comum é sobre cancelamento de corrotinas. Como cancelar uma corrotina corretamente? Use Job.cancel() e verifique o estado através de ensureActive() ou isActive dentro de operações longas.
2. Funções inline e tipos reified
Desenvolvedores avançados devem entender por que as funções inline são necessárias. A pergunta pode ser: "Por que o Kotlin não permite usar tipos reified sem inline?"
Resposta: Tipos reified (reificados) funcionam apenas dentro de funções inline, porque o código dessa função é inserido diretamente no local da chamada. O compilador substitui o tipo concreto durante a compilação, o que é impossível para funções genéricas comuns devido ao apagamento de tipo na JVM.
Exemplo que demonstra o poder do reified:
inline fun <reified T> isInstance(value: Any): Boolean { return value is T}
fun main() { println(isInstance<String>("Hello")) // true println(isInstance<Int>("Hello")) // false}Também perguntarão sobre noinline e crossinline. noinline proíbe a inserção de um parâmetro lambda específico, enquanto crossinline proíbe o uso de return dentro do lambda (retorno não local).
3. Delegados: Delegates.observable, vetoable e delegados personalizados
A pergunta sobre delegados é clássica. O nível avançado implica não apenas conhecer os delegados embutidos (lazy, observable), mas também saber criar os seus próprios.
Exemplo: "Como implementar um delegado que registra cada alteração de propriedade?"
import kotlin.properties.ReadWritePropertyimport kotlin.reflect.KProperty
class LoggingDelegate<T>(private val initialValue: T) : ReadWriteProperty<Any?, T> { private var value = initialValue
override fun getValue(thisRef: Any?, property: KProperty<*>): T { println("Leitura de ${property.name}: $value") return value }
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { println("Escrita de ${property.name}: $value") this.value = value }}
class User { var