Ответ
Это термин, введённый Тони Хоаром, для обозначения введения концепции null в языки программирования. В контексте Dart и Flutter это приводит к ошибкам времени выполнения, когда код пытается вызвать метод или обратиться к свойству у null-значения (например, NoSuchMethodError).
С введением null safety (Dart 2.12+) система типов помогает предотвратить эти ошибки на этапе компиляции. Переменные по умолчанию не могут быть null, если явно не помечены как nullable с помощью ?.
Пример и безопасная работа с nullable-типами:
String? nullableName; // Может быть String или null
String regularName = 'Flutter'; // Не может быть null
// Опасный вызов — может вызвать ошибку во время выполнения, если nullableName == null
// print(nullableName.length);
// Безопасные подходы:
// 1. Проверка на null (flow analysis)
if (nullableName != null) {
print(nullableName.length); // В этой области видимости тип — String
}
// 2. Оператор безопасного вызова `?.`
print(nullableName?.length); // Выполнит length, если не null, иначе вернёт null
// 3. Оператор объединения `??` для предоставления значения по умолчанию
print(nullableName?.length ?? 0); // Если null, то использует 0
// 4. Оператор утверждения `!` (используйте с осторожностью, только если уверены)
print(nullableName!.length); // Говорит компилятору: "это не null". Выбросит ошибку, если окажется null.
Основная практика — максимально использовать не-nullable типы и явно обрабатывать nullable случаи через ?, ?? и условные проверки, чтобы ошибки на миллион долларов оставались в прошлом.
Ответ 18+ 🔞
А, ну это же классика, ёпта! Тот самый "ошибка на миллион долларов", который Тони Хоар сам назвал своим "миллиардным косяком". Представь: пишешь код, всё летает, а потом — бац! — какая-то переменная оказалась null, и твоё приложение накрывается медным тазом с криком NoSuchMethodError. Чистая рулетка, доверия ебать ноль.
Но потом в Dart 2.12 пришла null safety, и жизнь стала немного проще. Теперь система типов тебя страхует. По умолчанию, если ты не указал иначе, переменная null быть не может. Хочешь иметь возможность хранить в ней "ничего"? Тогда явно пометь вопросительным знаком — String?. И компилятор сразу начинает приставать: "Чувак, а ты уверен, что там что-то есть? А ну-ка подумай, э бошка!"
Вот смотри, как это работает на практике, чтобы не облажаться:
String? nullableName; // Может быть строкой, а может и пустотой, хуй с горы
String regularName = 'Flutter'; // Тут всегда будет текст, иначе компилятор взвоет
// Раньше бы тут написали и молились. Сейчас — нельзя, опасно!
// print(nullableName.length); // Пизда рулю, если nullableName == null
// Теперь безопасные способы, чтобы не бздеть:
// 1. Старая добрая проверка (компилятор умный, он поймёт)
if (nullableName != null) {
print(nullableName.length); // Тут уже точно String, можно спать спокойно
}
// 2. Оператор безопасного вызова `?.` — сделает дело, если есть что, иначе вернёт null и не позорится
print(nullableName?.length);
// 3. Оператор `??` — для тех, кто любит подстраховаться. "Нет значения? Да похуй, вот тебе дефолтное!"
print(nullableName?.length ?? 0); // Если null, то печатаем ноль
// 4. Восклицательный знак `!` — это как крик "Я уверен, ёба!" Только если не уверен — будет тебе хиросима.
print(nullableName!.length); // Говоришь компилятору "заткнись и работай". Вылетит, если соврал.
Суть в чём: старайся по максимуму использовать обычные, не-nullable типы. А если уж приспичило с "пустотой" работать, обрабатывай её явно через эти операторы. Тогда эти ебаные ошибки на миллион долларов останутся в прошлом, как страшный сон.