DMarlon Studio

Lesson 15 · 15 of 20

Null safety · Dart

Understand Dart's null safety: nullable types with ?, the ??, ?., ! and ??= operators, and how an if != null check changes the type.

Dart · Null safety in DMarlon Studio: the example's code and its output in the terminal

`null` means "no value". In Dart a String can never be null; if a variable may end up without a value, its type gets a `?`: String? nickname; starts out as null. This null safety lets Dart warn you before running if you use something that might be missing.

The findEmail function returns String? because looking something up in a map may find nothing. The `??` operator gives a default value when the left side is null: nickname ?? 'none' prints none.

`?.` calls a method only when the value is not null; if it is, the result is null with no error. Marta is not in the address book, so marta?.toUpperCase() gives null, and marta?.length ?? 0 combines both operators to give 0.

After checking if (ana != null), Dart knows that inside the block ana has a value and treats it as a plain String: you can call split straight away. The `!` operator says "I am sure this is not null": emails['Luis']! gives a String, but if the key were missing the program would crash, so use it with care.

Finally, `??=` assigns only if the variable is still null: the first nickname ??= 'Nana' gives it a value and the second one changes nothing.

Code · main.dart

// A ? after the type means it may hold null: "no value".String? findEmail(Map<String, String> book, String name) => book[name];void main() {  var emails = {'Ana': 'ana@mail.com', 'Luis': 'luis@work.org'};  // String can never be null; String? can, and starts as null.  String owner = 'Ana';  String? nickname;  print('Owner: $owner, nickname: $nickname');  // ?? gives a default value when the left side is null.  print('Nickname: ${nickname ?? 'none'}');  // ?. calls the method only if the value is not null.  String? marta = findEmail(emails, 'Marta');  print('Marta: ${marta?.toUpperCase()}');  print('Marta: ${marta?.length ?? 0} characters');  // After checking != null, Dart treats it as a plain String.  String? ana = findEmail(emails, 'Ana');  if (ana != null) {    print('Ana writes from ${ana.split('@')[1]}');  }  // ! means "I am sure it is not null" (and fails if it is).  String luis = emails['Luis']!;  print('Luis: ${luis.length} characters');  // ??= gives a value only if the variable is still null.  nickname ??= 'Nana';  nickname ??= 'Other';  print('Nickname now: $nickname');}

Output · dart run main.dart

Owner: Ana, nickname: null
Nickname: none
Marta: null
Marta: 0 characters
Ana writes from mail.com
Luis: 13 characters
Nickname now: Nana

Key points

  • String? allows null; String does not.
  • a ?? b gives b when a is null.
  • a?.method() gives null instead of failing.
  • a! claims it is not null (and fails if it is).
  • After if (a != null), a has the type without ?.

Exercise

Add a String? findPhone(String name) function with a map of phone numbers and print, for three names (one of them missing), the phone number or no phone using ??.