Kotlin: Bullseye or Miss?
\nKotlin is not just "Java without boilerplate." It's a language that won Google's heart, outpaced Swift in growth rates, and became a mandatory requirement in mobile developer job postings. But here's the paradox: many come to an interview thinking "I know Java — I'll figure it out," and leave with red eyes. Because Kotlin is a different world: without null, with coroutines and extension functions that break the patterns.
\nWe at PythonLib (yes, we're about Python, but Kotlin is a must-have for modern backend and mobile) have compiled a real case study: how to ace a Kotlin interview. No fluff — only code, logic, and secret tips that courses don't teach.
\n\n1. Why Kotlin is Not "Just Java 2.0"?
\nThe first question you'll be asked: "What is the fundamental difference between Kotlin and Java?" If you say "shorter syntax" — you'll be politely asked to leave. The main difference is null safety at the type level. In Java, you might forget to check an object for null and get an NPE at runtime. In Kotlin, the compiler won't even let you compile code if there's a risk of null.
\n// Java\nString name = null;\nint length = name.length(); // NPE at runtime\n\n// Kotlin\nvar name: String? = null\nval length = name?.length ?: 0 // Safe: length = 0\nBut that's the basics. The interviewer will dig deeper: they'll ask about !! (non-null assertion), the Elvis operator ?:, and safe calls ?.. Your task is to show that you understand: !! is evil, and ?: is your friend.
- \n
- Safe call (?.) — if the object is null, returns null. \n
- Elvis (?:) — if the left side is null, take the value from the right. \n
- !! — use only if you are 100% sure, otherwise — a bug. \n
2. Extension Functions: Magic You Need to Explain
\nQuestion: "How do you add a method to a class you cannot modify?" In Java — the Decorator pattern or a Util class. In Kotlin — extension functions. This is not a real modification of the class, but syntactic sugar that makes code readable.
\n// Extension function for String\nfun String.isEmail(): Boolean {\n return this.contains("@") && this.contains(".")\n}\n\n// Usage\nval email = "user@pythonlib.ru"\nprintln(email.isEmail()) // true\nThe interviewer might ask: "Can you override an extension function?" Answer: no, it's a static call, not dynamic. If you declare a function with the same name in the class, the class method takes priority.
\n\n3. Sealed Class vs Enum: When to Use What?
\nThis is a classic middle-level question. Enum — for a fixed set of constants (days of the week, statuses). Sealed class — for a restricted hierarchy of types, where each element can have its own state.
\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}\nWhy is this important? Because when with a sealed class guarantees that you have handled all cases. The compiler won't let you forget about a new type if you add it to the sealed class.
4. Coroutines: How Not to Fail at Asynchrony
\nThe topic where 70% of candidates stumble. Coroutines are not threads. They are lightweight "threads" that can suspend without blocking a thread.
\nsuspend fun fetchData(): String {\n delay(1000) // Does not block the thread!\n return "Data from PythonLib"\n}\n\nfun main() = runBlocking {\n launch {\n val result = fetchData()\n