← Назад к вопросам

Что такое null-safety в Kotlin?

2.3 Middle🔥 131 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Null-Safety в Kotlin

Null-safety (безопасность от null) — это встроенный механизм в Kotlin, который предотвращает NullPointerException на этапе компиляции, а не во время выполнения. Это один из ключевых отличий Kotlin от Java и решает классическую проблему, которую Тони Хоар назвал "миллиардной ошибкой".

Основной принцип

В Kotlin каждый тип разделяется на две категории:

  • Non-nullable type (не допускает null): String, Int, List<String>
  • Nullable type (допускает null): String?, Int?, List<String>?
// Java — может быть null (неизвестно):
String name = getName();

// Kotlin — явно указываем, может ли быть null:
val name: String = getName()     // Точно не null
val nameOrNull: String? = getName() // Может быть null

Типизация и компиляция

// ✅ Kotlin — безопасно
val name: String = "Alice"
println(name.length) // Компилятор знает, что name не null

// ❌ Kotlin — ошибка компиляции
val nameOrNull: String? = "Bob"
println(nameOrNull.length) // Ошибка! Нужна проверка

// ✅ Kotlin — безопасно (после проверки)
if (nameOrNull != null) {
    println(nameOrNull.length) // Компилятор понимает smart cast
}

Методы работы с nullable типами

1. Safe Call Operator (?.)

val user: User? = getUser()
val name: String? = user?.name // Если user == null, то name == null
println(name) // null или имя

2. Elvis Operator (?:)

val name: String = user?.name ?: "Unknown"
// Если user.name == null, то используется "Unknown"

val age: Int = user?.age ?: 0
println("Age: $age") // 0, если user == null

3. Not-null Assertion Operator (!!)

val user: User? = getUser()
val name: String = user!!.name // Бросает NPE, если user == null

⚠️ Используй !! только если абсолютно уверен, что значение не null.

4. let и другие scope функции

val user: User? = getUser()

// let выполняется только если user != null
user?.let {
    println(it.name) // it — это user (и точно не null)
    println(it.age)
}

// Цепочка операций
user?.let { u ->
    u.updateLastSeen()
    sendNotification(u)
}

5. when с null-проверкой

val user: User? = getUser()

when (user) {
    null -> println("No user")
    else -> println("User: ${user.name}") // user точно не null
}

Практические примеры

Пример 1: Цепочка null-проверок

data class User(val profile: Profile?)
data class Profile(val settings: Settings?)
data class Settings(val theme: String)

// Java-стиль (громоздко):
if (user != null && user.getProfile() != null && user.getProfile().getSettings() != null) {
    println(user.getProfile().getSettings().getTheme())
}

// Kotlin — much cleaner:
user?.profile?.settings?.theme?.let { theme ->
    println(theme)
}

Пример 2: Функция с nullable параметром

fun processUser(user: User?) {
    // Безопасная работа с user
    val name = user?.name ?: "Anonymous"
    val email = user?.email
    
    println("Name: $name")
    email?.let { println("Email: $it") }
}

processUser(null)       // Работает без ошибок
processUser(user)       // Работает с данными

Пример 3: Возвращаемое значение может быть null

fun findUserById(id: Int): User? {
    return users.find { it.id == id } // Может вернуть null
}

// Использование
val user = findUserById(123)
if (user != null) {
    println("Found: ${user.name}")
} else {
    println("User not found")
}

// Или проще:
findUserById(123)?.let { println("Found: ${it.name}") }

Пример 4: Коллекции с nullable элементами

val users: List<User?> = listOf(user1, null, user3)

// Отфильтруем null значения
val nonNullUsers = users.filterNotNull() // List<User>

// mapNotNull — трансформация и удаление null
val names = users.mapNotNull { it?.name } // List<String>

Сравнение Java и Kotlin

// Java — нужны проверки везде
String name = user.getName();
if (name != null && name.length() > 0) {
    // ...
}

// Kotlin — компилятор требует явности
val name: String? = user.name
if (name != null && name.isNotEmpty()) {
    // Компилятор знает, что name не null здесь (smart cast)
}

Advantages of Kotlin Null-Safety

  • Compile-time safety: ошибки выявляются на этапе компиляции
  • No runtime overhead: нет проверок во время выполнения
  • Clear API contracts: сигнатура функции явно показывает, может ли быть null
  • Reduced code verbosity: меньше null-проверок
  • Interoperability с Java: Kotlin может работать с Java кодом (с предупреждениями)

Заключение

Null-safety в Kotlin — это революционный подход к безопасности типов, который делает код более надежным и избавляет от целого класса ошибок. Это один из главных аргументов в пользу использования Kotlin вместо Java в новых проектах.

Что такое null-safety в Kotlin? | PrepBro