Null Safety
Null Safety
Introduction
In this lesson, you'll learn about null safety in Java. Coming from TypeScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In TypeScript, you're familiar with null safety.
Java has its own approach to null safety, which we'll explore step by step.
The Java Way
Let's see how Java handles this concept. Here's a typical example:
import java.util.Optional;
public class User {
private String name;
private Optional<Address> address;
public Optional<String> getCity() {
return address.flatMap(Address::getCity);
}
}
// Using Optional
Optional<String> city = user.getCity();
String result = city.orElse("Unknown");
// Or with map/flatMap chain
String port = Optional.ofNullable(System.getenv("PORT"))
.orElse("3000");Comparing to TypeScript
Here's how you might have written similar code in TypeScript:
interface User {
name: string;
address?: {
city?: string;
};
}
function getCity(user: User | null): string {
return user?.address?.city ?? "Unknown";
}
// Nullish coalescing
const port = process.env.PORT ?? "3000";You may be used to different syntax or behavior.
TypeScript uses ?. (optional chaining) and ?? (nullish coalescing)
You may be used to different syntax or behavior.
Java uses Optional<T> as an explicit wrapper — similar to Haskell's Maybe
You may be used to different syntax or behavior.
Java's NullPointerException is the most common runtime error — handle proactively
You may be used to different syntax or behavior.
Optional.orElse() is equivalent to the ?? operator
Step-by-Step Breakdown
1. Optional<T> Replaces Nullable Types
Java Optional<T> is an explicit container that either holds a value or is empty. Use it for method return types when a value might be absent.
function findUser(id: number): User | null { ... }public Optional<User> findUser(int id) { ... }2. Optional Chaining vs flatMap
TypeScript's ?. chains become Optional.flatMap() chains in Java.
const city = user?.address?.city;Optional<String> city = Optional.ofNullable(user)
.flatMap(u -> Optional.ofNullable(u.getAddress()))
.flatMap(a -> Optional.ofNullable(a.getCity()));3. orElse and orElseGet
Optional.orElse(default) mirrors the ?? operator. orElseGet(() -> compute()) is lazy and preferred when the default is expensive to compute.
const value = maybeNull ?? "default";String value = optional.orElse("default");
// Lazy:
String value2 = optional.orElseGet(() -> computeDefault());4. NullPointerException — The Billion Dollar Mistake
Java references can be null by default. Modern Java uses @NonNull/@Nullable annotations and Optional to prevent NPEs. Never assume a reference is non-null without checking.
// TypeScript strict mode prevents null dereference at compile time// Java — check before use:
if (user != null) {
System.out.println(user.getName());
}
// Or with Objects utility:
Objects.requireNonNull(user, "user must not be null");Common Mistakes
When coming from TypeScript, developers often make these mistakes:
- TypeScript uses ?. (optional chaining) and ?? (nullish coalescing)
- Java uses Optional<T> as an explicit wrapper — similar to Haskell's Maybe
- Java's NullPointerException is the most common runtime error — handle proactively
Key Takeaways
- Java Optional<T> wraps possibly-absent values — use it for return types
- Optional.orElse() is the ?? operator equivalent
- Optional.flatMap() chains replace optional chaining (?.) for nested access
- NullPointerException is Java's most common bug — always validate references