Как пройти собеседование по Kotlin: разбор топ-вопросов с примерами
Kotlin прочно занял нишу современного языка для Android-разработки и бэкенда на JVM. Если вы готовитесь к техническому интервью, важно не просто знать синтаксис, но и понимать философию языка: безопасность, лаконичность и совместимость с Java. В этой статье мы разберем ключевые вопросы, которые чаще всего задают на собеседованиях по Kotlin, с реальными примерами кода.
1. Null Safety: как Kotlin решает проблему null
Один из главных козырей Kotlin — встроенная защита от NullPointerException. На собеседовании вас обязательно спросят про nullable и non-null типы.
Вопрос: Чем отличается String? от String? Как безопасно работать с nullable?
Ответ: Тип String гарантирует, что переменная никогда не будет null. String? допускает null. Для безопасного доступа используются операторы ?., ?: (Элвис) и !! (только если уверены на 100%).
fun main() {
val name: String? = null
// Безопасный вызов
println(name?.length) // null
// Значение по умолчанию
val length = name?.length ?: 0
println(length) // 0
// Принудительное извлечение (риск NPE)
// println(name!!.length) // Ошибка!
}
Дополнительный вопрос: Что такое lateinit и lazy?
lateinit— для переменных, которые инициализируются позже (толькоvar).lazy— для делегированной инициализации (толькоval).
class User {
lateinit var email: String
val config by lazy { loadConfig() }
fun init() {
email = "test@example.com"
}
}
2. Корутины: асинхронность без боли
Корутины (coroutines) — must-have для современного Kotlin. Интервьюеры проверяют понимание suspend, launch, async и диспетчеров.
Вопрос: В чем разница между launch и async?
Ответ: launch запускает корутину и возвращает Job (без результата). async возвращает Deferred, из которого можно получить результат через await().
suspend fun fetchData(): String {
delay(1000)
return "Данные загружены"
}
fun main() = runBlocking {
// launch: без результата
val job = launch {
println("Задача 1 выполнена")
}
// async: с результатом
val deferred = async {
fetchData()
}
println(deferred.await()) // "Данные загружены"
job.join()
}
Вопрос: Какие диспетчеры (Dispatchers) вы знаете?
Dispatchers.Main— для UI (Android).Dispatchers.IO— для ввода-вывода, сети.Dispatchers.Default— для CPU-интенсивных задач.Dispatchers.Unconfined— не привязан к конкретному потоку (используется редко).
3. Extension functions и Sealed class: расширяем возможности
Kotlin позволяет добавлять новые функции к существующим классам без наследования. Это часто спрашивают в контексте архитектуры.
Вопрос: Что такое extension functions? Приведите пример.
Ответ: Это функции, которые объявляются вне класса, но вызываются как его методы. Они не изменяют класс, а лишь добавляют синтаксический сахар.
// Extension function для String
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
fun main() {
val email = "user@example.com"
println(email.isEmail()) // true
val text = "hello"
println(text.isEmail()) // false
}
Вопрос: Для чего нужны sealed class? Чем они отличаются от enum?
Ответ: Sealed class (запечатанные классы) используются для представления ограниченной иерархии типов. В отличие от enum, каждый подтип может иметь свое состояние и поведение. Идеально подходят для состояний UI (загрузка, успех, ошибка).
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val message: String) : Result<Nothing>()
object Loading : Result<Nothing>()
}
fun handleResult(result: Result<String>) {
when (result) {
is Result.Loading -> println("Загрузка...")
is Result.Success -> println("Успех: ${result.data}")
is Result.Error -> println("Ошибка: ${result.message}")
}
}
fun main() {
handleResult(Result.Loading)
handleResult(Result.Success("Kotlin"))
}
4. Kotlin vs Java: что нужно знать мигранту
Если вы переходите с Java, интервьюер обязательно спросит про ключевые отличия. Будьте готовы показать, как Kotlin делает код чище.
Вопрос: Как Kotlin обрабатывает checked exceptions?
Ответ: В Kotlin нет checked exceptions. Все исключения — unchecked. Это упрощает код, но требует дисциплины: используйте try-catch или Result для обработки ошибок.
Вопрос: Что такое data class? Какие методы генерируются автоматически?
Ответ: data class автоматически генерирует equals(), hashCode(), toString(), copy() и деструктуризацию. Это заменяет тонны бойлерплейта из Java.
data class Person(val name: String, val age: Int)
fun main() {
val alice = Person("Alice", 30)
val bob = alice.copy(name = "Bob")
println(alice) // Person(name=Alice, age=30)
println(bob) // Person(name=Bob, age=30)
// Деструктуризация