← Назад к вопросам
Объясните разницу между val и var в Kotlin. Что такое nullable и non-nullable типы?
1.2 Junior🔥 221 комментариев
#Kotlin основы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
val vs var и Nullable vs Non-Nullable типы
val vs var
val — неизменяемая переменная (read-only), immutable
val name = "John"
name = "Jane" // Ошибка! Val cannot be reassigned
var — изменяемая переменная, mutable
var age = 25
age = 26 // OK! Можно переиспользовать
Разница:
| val | var |
|---|---|
| Нельзя переиспользовать | Можно переиспользовать |
| Потокобезопаснее | Требует синхронизации |
| Предпочтителен по умолчанию | Используется реже |
| Производительнее | Чуть медленнее |
Примеры
// val — используй для константных данных
val pi = 3.14
val isActive = true
val users = listOf("John", "Jane")
// var — используй для изменяющегося состояния
var counter = 0
var isLoading = false
var currentUser: User? = null
Nullable типы (может быть null)
Тип с ? означает, что переменная может содержать null:
val name: String? = null // OK
val age: Int? = null // OK
val city: String? = "Moscow"
println(city) // Moscow
val country: String? = null
println(country) // null
Non-nullable типы (НЕ может быть null)
Тип БЕЗ ? означает, что переменная ВСЕГДА имеет значение:
val name: String = "John" // OK
val age: Int = 25 // OK
val city: String = null // Ошибка! Type mismatch
val country: String = "Russia" // OK
Null Safety в Kotlin
Проблема в Java:
String name = getNullableString();
int length = name.length(); // NullPointerException!
Решение в Kotlin:
val name: String? = getNullableString()
val length = name?.length // Safe call, может быть null
Работа с Nullable типами
1. Safe Call Operator (?.):
val user: User? = getUser()
val name = user?.name // name: String? (может быть null)
println(name) // null или значение
2. Elvis Operator (?:):
val userName = user?.name ?: "Guest"
// Если user?.name == null, используй "Guest"
3. Not-null Assertion (!!):
val user: User? = getUser()
val name = user!!.name // Кидаем NullPointerException если null
// Используй только когда УВЕРЕН в значении!
4. Safe Cast (as?):
val any: Any = "String"
val str = any as? String // "String"
val num = any as? Int // null
Пример: обработка null
val user: User? = getUser()
// Плохо — использование !!
val email = user!!.email
// Хорошо — safe call + elvis
val email = user?.email ?: "unknown@example.com"
// Хорошо — let для non-null
user?.let { safeUser ->
println("Имя: ${safeUser.name}")
println("Email: ${safeUser.email}")
} ?: run {
println("User is null")
}
Пример: Collections
val numbers: List<Int> = listOf(1, 2, 3) // Не может быть null
val nullableList: List<Int>? = null // Сам список может быть null
val listWithNulls: List<Int?> = listOf(1, null, 3) // Элементы могут быть null
// Разные типы!
val list1: List<String> // Non-null список non-null строк
val list2: List<String>? // Nullable список non-null строк
val list3: List<String?> // Non-null список nullable строк
val list4: List<String?>? // Nullable список nullable строк
Пример в ViewModel
class UserViewModel : ViewModel() {
val userName: String = "John" // Никогда null
val userEmail: String? = null // Может быть null
fun displayUser() {
// Безопасное обращение
val email = userEmail ?: "No email"
println(email)
}
}
Пример в Coroutine
val result: Result<User>? = null
val user = result?.getOrNull() // User?
println(user?.name ?: "Unknown") // Safe handling
// Или
result?.let { safeResult ->
val user = safeResult.getOrNull()
println(user?.name)
}
Правила использования
Используй val:
- По умолчанию для всего
- Для параметров функций
- Для properties в data class
- Для constantes
Используй var:
- Только если переменная меняется
- В состояниях UI (remember, mutableState)
- В счётчиках и флагах
Nullable типы:
- Когда данные могут отсутствовать
- Для optional параметров
- При работе с API
- Для обработки ошибок
Non-Nullable типы:
- По умолчанию для всего
- Для гарантированных данных
- Для повышения типобезопасности
Вывод
- val — неизменяемо, var — изменяемо
- String? — может быть null, String — никогда null
- Kotlin защищает от null-ошибок на уровне типов
- Используй safe operators для работы с nullable типами
- Предпочитай non-nullable типы и val по умолчанию