Como passar em uma entrevista de Kotlin: principais perguntas de nível avançado
\n\nUma entrevista para a posição de desenvolvedor Kotlin não é apenas uma verificação de sintaxe. No nível avançado, os entrevistadores querem ver um profundo entendimento da linguagem, suas características e a capacidade de escrever código eficiente, conciso e seguro. Neste artigo, analisaremos os tópicos-chave que frequentemente aparecem em entrevistas técnicas: corrotinas, funções inline, classes Sealed, delegação e truques de expressões lambda. O material foi preparado para o portal educacional PythonLib, onde ajudamos desenvolvedores a sistematizar conhecimentos.
\n\n1. Corrotinas (Coroutines) e Structured Concurrency
\nCorrotinas são a base da programação assíncrona em Kotlin. Perguntas sobre este tópico mostram se você entende como funciona o agendador, o contexto e o tratamento de exceções.
\n\nO que é Structured Concurrency e para que serve?
\nStructured Concurrency (concorrência estruturada) é um princípio onde o ciclo de vida de uma corrotina está vinculado a um escopo (scope). Se a corrotina pai for cancelada, todas as tarefas filhas são automaticamente canceladas. Isso evita vazamentos de memória e torna o código previsível.
\n\nfun main() = runBlocking {\n launch {\n delay(1000)\n println("Tarefa 1 concluída")\n }\n launch {\n delay(500)\n println("Tarefa 2 concluída")\n }\n println("Thread principal não está bloqueada")\n}\n\n\nDiferença entre launch e async
\nlaunch inicia uma corrotina que não retorna resultado (Unit). async retorna um Deferred, do qual você pode obter o resultado através de await(). async é útil para cálculos paralelos.
val deferred1 = async { calculateSum(10, 20) }\nval deferred2 = async { calculateSum(30, 40) }\nval result = deferred1.await() + deferred2.await()\nprintln("Soma: $result")\n\n\nTratamento de exceções em corrotinas
\nUse try-catch dentro da corrotina ou CoroutineExceptionHandler para tratamento global. É importante lembrar que exceções em launch se propagam para cima na hierarquia, enquanto em async são armazenadas até a chamada de await().
val handler = CoroutineExceptionHandler { _, exception ->\n println("Erro: ${exception.message}")\n}\n\nfun main() = runBlocking {\n val job = launch(handler) {\n throw RuntimeException("Algo deu errado")\n }\n}\n\n\n2. Funções inline, reified e crossinline
\nEsses mecanismos permitem otimizar o desempenho e trabalhar com genéricos em tempo de execução. Os entrevistadores frequentemente perguntam sobre a diferença entre inline, noinline e crossinline.
Para que servem as funções inline?
\nFunções inline substituem o corpo da função diretamente no local da chamada. Isso elimina a sobrecarga de criação de objetos lambda. Particularmente útil para funções de ordem superior (higher-order functions).
\n\ninline fun measureTime(action: () -> Unit) {\n val start = System.currentTimeMillis()\n action()\n println("Tempo: ${System.currentTimeMillis() - start} ms")\n}\n\n\nO que é reified?
\nCom reified, você pode obter informações sobre o tipo dentro de uma função inline, o que é impossível para genéricos comuns devido ao apagamento de tipo (type erasure).
inline fun <reified T> isInstance(value: Any): Boolean {\n return value is T\n}\n\nfun main() {\n println(isInstance<String>("Hello")) // true\n}\n\n\nDiferença entre noinline e crossinline
\n- \n
noinline— proíbe a inline de um lambda específico (por exemplo, se ele for passado para outra função). \n crossinline— permite a inline, mas proíbe o retorno não local (non-local return) do lambda, o que é seguro para chamadas assíncronas. \n