empty<T> static method
Returns an empty Optional instance. No value is present for this Optional.
API Note
Though it may be tempting to do so, avoid testing if an object is empty
by comparing with ==
against instances returned by Optional.empty.
There is no guarantee that it is a singleton. Instead, use isEmpty or isPresent.
Example
Optional<String> empty = Optional.empty();
print(empty.isEmpty()); // true
print(empty.isPresent()); // false
// Don't do this - unreliable
// if (someOptional == Optional.empty()) { ... }
// Do this instead
if (someOptional.isEmpty()) { ... }
Returns an empty Optional.
A container object which may or may not contain a non-null value.
If a value is present, isPresent returns true
. If no value is present,
the object is considered empty and isPresent returns false
.
Additional methods that depend on the presence or absence of a contained value are provided, such as orElse (returns a default value if no value is present) and ifPresent (performs an action if a value is present).
Usage Examples
Basic Creation and Checking
// Create an Optional with a value
Optional<String> name = Optional.of("John");
print(name.isPresent()); // true
print(name.get()); // "John"
// Create an empty Optional
Optional<String> empty = Optional.empty();
print(empty.isPresent()); // false
print(empty.isEmpty()); // true
// Create Optional from nullable value
String? nullableValue = null;
Optional<String> fromNullable = Optional.ofNullable(nullableValue);
print(fromNullable.isEmpty()); // true
Safe Value Retrieval
Optional<String> name = Optional.of("Alice");
Optional<String> empty = Optional.empty();
// Using orElse for default values
print(name.orElse("Unknown")); // "Alice"
print(empty.orElse("Unknown")); // "Unknown"
// Using orElseGet with a supplier function
print(empty.orElseGet(() => "Generated default")); // "Generated default"
// Using orElseThrow
try {
print(empty.orElseThrow(() => Exception("No value present")));
} catch (e) {
print("Caught: $e"); // Caught: Exception: No value present
}
Conditional Operations
Optional<String> name = Optional.of("Bob");
Optional<String> empty = Optional.empty();
// Execute action if value is present
name.ifPresent((value) => print("Hello, $value!")); // Hello, Bob!
empty.ifPresent((value) => print("This won't print"));
// Execute different actions based on presence
name.ifPresentOrElse(
(value) => print("Found: $value"), // This executes
() => print("No value found")
);
empty.ifPresentOrElse(
(value) => print("Found: $value"),
() => print("No value found") // This executes
);
Transformations and Filtering
Optional<String> name = Optional.of("john doe");
// Transform the value if present
Optional<String> upperName = name.map((s) => s.toUpperCase());
print(upperName.get()); // "JOHN DOE"
// Chain transformations
Optional<int> nameLength = name
.map((s) => s.replaceAll(" ", ""))
.map((s) => s.length);
print(nameLength.get()); // 7
// Filter based on condition
Optional<String> longName = name.filter((s) => s.length > 5);
print(longName.isPresent()); // true
Optional<String> shortName = name.filter((s) => s.length < 5);
print(shortName.isEmpty()); // true
// FlatMap for nested Optionals
Optional<String> parseNumber(String s) {
try {
int.parse(s);
return Optional.of(s);
} catch (e) {
return Optional.empty();
}
}
Optional<String> input = Optional.of("123");
Optional<String> validNumber = input.flatMap(parseNumber);
print(validNumber.isPresent()); // true
Working with Collections
List<Optional<String>> optionals = [
Optional.of("apple"),
Optional.empty(),
Optional.of("banana"),
Optional.empty(),
Optional.of("cherry")
];
// Filter out empty optionals and get values
List<String> fruits = optionals
.where((opt) => opt.isPresent())
.map((opt) => opt.get())
.toList();
print(fruits); // [apple, banana, cherry]
// Using stream() method for functional processing
List<String> upperFruits = optionals
.expand((opt) => opt.stream())
.map((fruit) => fruit.toUpperCase())
.toList();
print(upperFruits); // [APPLE, BANANA, CHERRY]
Error Handling Patterns
// Safe division function
Optional<double> safeDivide(double a, double b) {
return b != 0 ? Optional.of(a / b) : Optional.empty();
}
// Usage with error handling
Optional<double> result = safeDivide(10, 2);
result.ifPresentOrElse(
(value) => print("Result: $value"), // Result: 5.0
() => print("Division by zero!")
);
// Chain operations safely
Optional<String> formatResult = safeDivide(15, 3)
.filter((value) => value > 1)
.map((value) => "Result: ${value.toStringAsFixed(2)}");
print(formatResult.orElse("No valid result")); // Result: 5.00
API Note
Optional is primarily intended for use as a method return type where
there is a clear need to represent "no result," and where using null
is likely to cause errors. A variable whose type is Optional should
never itself be null
; it should always point to an Optional instance.
Implementation
static Optional<T> empty<T>() => Optional<T>._(null);