What is null safety in Dart, and what are `?`, `!`, `??`, and `late` for?
Show answer — try answering out loud first
Null safety means that, by default, a variable can't be null unless you say so explicitly with ?. This moves an entire family of errors (the infamous NullPointerException) from runtime to compile time. ? marks a type as nullable, ! asserts that something isn't null, ?? provides a default value, and late promises to initialize later.
Before, any variable could be null, and the error only showed up at runtime. With null safety, String is never null; if you want to allow null, you write String?.
The key operators:
?(nullable type):String? namecan be text ornull.?.(safe access):user?.namereturnsnullifuseris null, instead of blowing up.??(default value):name ?? "guest"uses"guest"ifnameis null.??=(assign if null):name ??= "guest"assigns only ifnamewas null.!(null assertion):name!promises the compiler "this isn't null, trust me." If you're wrong, it blows up at runtime.late: promises that you'll initialize the variable before using it. Useful when you can't give it a value at declaration but know it will exist.
void main() {
String? name; // can be null
print(name); // null
// ?. safe access
print(name?.length); // null (doesn't blow up)
// ?? default value
print(name ?? "guest"); // "guest"
// ??= assign only if null
name ??= "Mike";
print(name); // "Mike"
// ! asserts it's not null (use with care)
String? maybe = "hi";
String safe = maybe!; // OK because it wasn't null
print(safe.length); // 2
// late: I promise to initialize before using
late String greeting;
greeting = "Hello";
print(greeting); // "Hello"
}
Overusing the ! operator to "silence" the compiler. variable! doesn't check anything: if the variable is null at that moment, your app blows up just like before null safety. ! should only be used when you truly know the value exists; in most cases ?? or a check with if (variable != null) is better.
"Null safety makes variables non-nullable by default; if I want to allow null, I use
?, like inString?. That turns null errors into compile-time errors instead of production crashes. To work with nullables I have?.for safe access,??to provide a default value, and!to assert that something isn't null, though I avoid!because it doesn't check anything and can blow up at runtime. I uselatewhen I know I'll initialize the variable later, not at declaration."
What does this code print?
String? text;
print(text?.length ?? -1);
See answer
It prints -1. text is null, so text?.length returns null (thanks to ?. it doesn't blow up). Then ?? -1 replaces that null with -1.