Kotlin: acertar em cheio ou errar o alvo?
\nKotlin — não é apenas "Java sem boilerplate". É uma linguagem que conquistou o coração do Google, ultrapassou Swift em ritmo de crescimento e se tornou item obrigatório nas vagas de desenvolvedores mobile. Mas eis o paradoxo: muitos chegam à entrevista pensando "eu sei Java — me viro", e saem com os olhos vermelhos. Porque Kotlin é um mundo diferente: sem null, com corrotinas e funções de extensão que quebram os padrões.
\nNós da PythonLib (sim, somos sobre Python, mas Kotlin é must-have para backend moderno e mobile) reunimos um caso real: como passar na entrevista de Kotlin com brilho. Nada de enrolação — apenas código, lógica e truques secretos que não ensinam nos cursos.
\n\n1. Por que Kotlin não é "apenas Java 2.0"?
\nA primeira pergunta que farão: "Qual a diferença fundamental entre Kotlin e Java?". Se você disser "a sintaxe é mais curta" — pedirão educadamente para sair. A principal diferença é a null safety em nível de tipos. Em Java, você pode esquecer de verificar se um objeto é null e obter um NPE em tempo de execução. Em Kotlin, o compilador não permite nem compilar o código se houver risco de null.
\n// Java\nString name = null;\nint length = name.length(); // NPE em tempo de execução\n\n// Kotlin\nvar name: String? = null\nval length = name?.length ?: 0 // Seguro: length = 0\nMas isso é o básico. O entrevistador vai mais fundo: perguntará sobre !! (non-null assertion), operador Elvis ?: e chamadas seguras ?.. Seu objetivo é mostrar que entende: !! é o mal, e ?: é seu amigo.
- \n
- Safe call (?.) — se o objeto for null, retorna null. \n
- Elvis (?:) — se o lado esquerdo for null, pega o valor da direita. \n
- !! — use apenas se tiver 100% de certeza, senão é bug. \n
2. Extension functions: a mágica que precisa ser explicada
\nPergunta: "Como adicionar um método a uma classe que você não pode modificar?". Em Java — padrão Decorator ou classe Util. Em Kotlin — extension functions. Não é uma modificação real da classe, mas um açúcar sintático que torna o código legível.
\n// Extension function para String\nfun String.isEmail(): Boolean {\n return this.contains("@") && this.contains(".")\n}\n\n// Uso\nval email = "user@pythonlib.ru"\nprintln(email.isEmail()) // true\nO entrevistador pode perguntar: "É possível sobrescrever uma extension function?". Resposta: não, é uma chamada estática, não dinâmica. Se você declarar uma função com o mesmo nome na classe, o método da classe tem prioridade.
\n\n3. Sealed class vs Enum: quando usar cada um?
\nEsta é uma pergunta clássica de nível médio. Enum — para um conjunto fixo de constantes (dias da semana, status). Sealed class — para uma hierarquia limitada de tipos, onde cada elemento pode ter seu próprio estado.
\nsealed class Result {\n data class Success(val data: String) : Result()\n data class Error(val code: Int, val message: String) : Result()\n object Loading : Result()\n}\n\nfun handleResult(result: Result) {\n when (result) {\n is Result.Success -> println("Data: ${result.data}")\n is Result.Error -> println("Error ${result.code}: ${result.message}")\n Result.Loading -> println("Loading...")\n }\n}\nPor que isso é importante? Porque when com sealed class é a garantia de que você tratou todos os casos. O compilador não permite que você esqueça um novo tipo, se você o adicionar à sealed class.
4. Corrotinas: como não falhar na assincronicidade
\nO tópico onde 70% dos candidatos quebram. Corrotinas não são threads. São "fios" leves que podem ser suspensos sem bloquear a thread.
\nsuspend fun fetchData(): String {\n delay(1000) // Não bloqueia a thread!\n return "Data from PythonLib"\n}\n\nfun main() = runBlocking {\n launch {\n val result = fetchData()\n