Menu
Coddy logo textTech

The ? and ! Operators

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

When working with nullable types, Dart provides two essential operators to access values safely. The null-aware access operator ?. and the null assertion operator ! give you control over how you handle potentially null values.

The ?. operator safely accesses properties or methods on a nullable value. If the value is null, the entire expression returns null instead of crashing:

String? name = 'Alice';
print(name?.length);  // 5

name = null;
print(name?.length);  // null (no crash!)

The ! operator tells Dart "I'm certain this value is not null." It converts a nullable type to non-nullable, but throws an error if the value actually is null:

String? maybeName = 'Bob';
String definite = maybeName!;  // OK - we assert it's not null
print(definite.length);  // 3

String? empty = null;
// String crash = empty!;  // Runtime error! Value was null

Use ?. when you want to gracefully handle null values. Use ! only when you're absolutely certain a value exists - perhaps after checking it with an if statement or when you know the logic guarantees a value. Overusing ! defeats the purpose of null safety and can lead to runtime crashes.

challenge icon

Challenge

Easy

Let's build a product inventory system that demonstrates how to safely work with nullable values using the ?. and ! operators.

You'll create two files to organize your code:

  • product.dart: Define a Product class that represents an item in inventory. Some products have complete information, while others are still being cataloged. Your class should have:
    • A non-nullable String name - every product must have a name
    • A non-nullable double price - every product must have a price
    • A nullable String? description - some products don't have descriptions yet
    • A nullable String? category - some products haven't been categorized
    • A constructor that takes name and price as required parameters
    • A method getDescriptionLength() that returns the length of the description using ?., or null if there's no description
    • A method getCategoryUppercase() that returns the category in uppercase using ! - this method assumes the category has been set
    • A method displayProduct() that prints the product information, showing No description when description is null and Uncategorized when category is null
  • main.dart: Import your product class and demonstrate both operators:
    • Create a product named 'Laptop' with price 999.99, then set its description to 'High-performance computing device' and category to 'Electronics'
    • Create a product named 'Mystery Item' with price 49.99 (leave description and category as null)
    • For the Laptop: call displayProduct(), print Description length: [length] using getDescriptionLength(), and print Category: [uppercase] using getCategoryUppercase()
    • For the Mystery Item: call displayProduct() and print Description length: [length] using getDescriptionLength() (this will show null)

The displayProduct() method should print in this format:

Product: [name] - $[price]
Description: [description or "No description"]
Category: [category or "Uncategorized"]

Expected output:

Product: Laptop - $999.99
Description: High-performance computing device
Category: Electronics
Description length: 32
Category: ELECTRONICS
Product: Mystery Item - $49.99
Description: No description
Category: Uncategorized
Description length: null

Cheat sheet

The null-aware access operator ?. safely accesses properties or methods on nullable values. If the value is null, it returns null instead of throwing an error:

String? name = 'Alice';
print(name?.length);  // 5

name = null;
print(name?.length);  // null (no crash!)

The null assertion operator ! converts a nullable type to non-nullable. Use it only when you're certain the value is not null, as it will throw a runtime error if the value is actually null:

String? maybeName = 'Bob';
String definite = maybeName!;  // OK - asserts it's not null
print(definite.length);  // 3

String? empty = null;
// String crash = empty!;  // Runtime error!

Use ?. for graceful null handling and ! only when you're absolutely certain a value exists.

Try it yourself

import 'product.dart';

void main() {
  // TODO: Create a product named 'Laptop' with price 999.99
  // Then set its description to 'High-performance computing device'
  // And set its category to 'Electronics'
  
  // TODO: Create a product named 'Mystery Item' with price 49.99
  // Leave description and category as null
  
  // TODO: For the Laptop:
  // - Call displayProduct()
  // - Print "Description length: [length]" using getDescriptionLength()
  // - Print "Category: [uppercase]" using getCategoryUppercase()
  
  // TODO: For the Mystery Item:
  // - Call displayProduct()
  // - Print "Description length: [length]" using getDescriptionLength()
}
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