Menu
Coddy logo textTech

Nullable vs Non-Nullable

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 24 of 110.

Now that you understand why null safety matters, let's look at how to declare variables that can hold null. In Dart, you make a type nullable by adding a ? after the type name.

String name = 'Alice';   // Non-nullable - must always have a value
String? nickname;        // Nullable - can be null or a String

print(name);      // Alice
print(nickname);  // null

The key difference is that non-nullable types guarantee a value exists, while nullable types explicitly allow the absence of a value. This distinction applies to all types:

int count = 10;       // Must have a value
int? optionalCount;   // Can be null

List<String> items = [];      // Must be a list (can be empty)
List<String>? maybeItems;     // Could be null (no list at all)

Notice that an empty list [] is different from null. An empty list exists but contains nothing; null means no list exists at all.

The compiler enforces these rules strictly. You cannot assign null to a non-nullable variable, and you cannot use a nullable variable where a non-nullable one is expected without first checking for null:

String? maybeName = 'Bob';
// String definite = maybeName;  // Error! Can't assign nullable to non-nullable

In the next lesson, you'll learn the operators Dart provides to safely work with nullable values.

challenge icon

Challenge

Easy

Let's build a movie watchlist system that demonstrates the difference between required information and optional information using nullable and non-nullable types.

You'll create two files to organize your code:

  • movie.dart: Define a Movie class that represents a film in your watchlist. Every movie must have a title and release year (these are always required), but some additional details might not be available for every movie. Your class should have:
    • A non-nullable String title - every movie must have a title
    • A non-nullable int year - every movie must have a release year
    • A nullable String? director - the director might be unknown
    • A nullable double? rating - not all movies have been rated yet
    • A constructor that takes title and year as required parameters
    • A displayInfo() method that prints the movie's information, showing Unknown for missing director and Not rated for missing rating
  • main.dart: Import your movie class and create a small watchlist demonstrating both complete and incomplete movie data:
    • Create a movie with title 'Inception' and year 2010, then set its director to 'Christopher Nolan' and rating to 8.8
    • Create a movie with title 'The Matrix' and year 1999, then set only its rating to 8.7 (leave director as null)
    • Create a movie with title 'Upcoming Film' and year 2025 (leave both director and rating as null)
    • Call displayInfo() on each movie in the order listed above

The displayInfo() method should print in this exact format:

[title] ([year])
Director: [director or "Unknown"]
Rating: [rating or "Not rated"]

Notice how the non-nullable fields (title and year) are always guaranteed to have values, while the nullable fields (director? and rating?) can remain unset. This reflects real-world scenarios where some data is essential and some is optional.

Expected output:

Inception (2010)
Director: Christopher Nolan
Rating: 8.8
The Matrix (1999)
Director: Unknown
Rating: 8.7
Upcoming Film (2025)
Director: Unknown
Rating: Not rated

Cheat sheet

To make a type nullable in Dart, add a ? after the type name:

String name = 'Alice';   // Non-nullable - must always have a value
String? nickname;        // Nullable - can be null or a String

This distinction applies to all types:

int count = 10;       // Must have a value
int? optionalCount;   // Can be null

List<String> items = [];      // Must be a list (can be empty)
List<String>? maybeItems;     // Could be null (no list at all)

An empty list [] is different from null. An empty list exists but contains nothing; null means no list exists at all.

The compiler enforces null safety rules strictly. You cannot assign null to a non-nullable variable, and you cannot use a nullable variable where a non-nullable one is expected without first checking for null:

String? maybeName = 'Bob';
// String definite = maybeName;  // Error! Can't assign nullable to non-nullable

Try it yourself

import 'movie.dart';

void main() {
  // TODO: Create a movie with title 'Inception' and year 2010
  // Then set its director to 'Christopher Nolan' and rating to 8.8
  
  // TODO: Create a movie with title 'The Matrix' and year 1999
  // Then set only its rating to 8.7 (leave director as null)
  
  // TODO: Create a movie with title 'Upcoming Film' and year 2025
  // Leave both director and rating as null
  
  // TODO: Call displayInfo() on each movie in order
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming