PY
JV

Python to Java

11 lessons

Progress0%
1Introduction2Variables & Types3Functions to Methods4Lists to Arrays5Dicts to Maps6Classes & OOP7Inheritance8Exception Handling9Modules to Packages10Ecosystem11Modern Java Features
All Mirror Courses
PY
JV
Modern Java Features
MirrorLesson 11 of 11
Lesson 11

Modern Java Features

Records, sealed classes, pattern matching, Optional — Java 14-21

Introduction

In this lesson, you'll learn about modern java features in Java. Coming from Python, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
PY
From Python:

In Python, you're familiar with records, sealed classes, pattern matching, optional — java 14-21.

JV
In Java:

Java has its own approach to records, sealed classes, pattern matching, optional — java 14-21, which we'll explore step by step.

The Java Way

Let's see how Java handles this concept. Here's a typical example:

JV
Java Example
// Java 16+: record — like Python @dataclass
public record Point(double x, double y) {}
// Auto-generates: constructor, getters, equals, hashCode, toString

Point p = new Point(1.0, 2.0);
System.out.println(p);         // Point[x=1.0, y=2.0]
System.out.println(p.equals(new Point(1.0, 2.0))); // true

// Java 17+: sealed classes — restrict subclasses
public sealed interface Shape
    permits Circle, Rectangle, Triangle {}

public record Circle(double radius)    implements Shape {}
public record Rectangle(double w, double h) implements Shape {}

// Java 21: pattern matching in switch (full)
String describe(Shape shape) {
    return switch (shape) {
        case Circle c    -> "circle r=" + c.radius();
        case Rectangle r -> "rect " + r.w() + "x" + r.h();
    }; // no default needed — sealed = exhaustive
}

// Java 16+: pattern matching instanceof
Object obj = "hello";
if (obj instanceof String s && s.length() > 3) {
    System.out.println(s.toUpperCase());
}

// Optional<T> — explicit null safety
Optional<String> findUser(int id) {
    return id == 1 ? Optional.of("Alice") : Optional.empty();
}
findUser(1)
    .map(String::toUpperCase)
    .ifPresent(System.out::println); // "ALICE"

Comparing to Python

Here's how you might have written similar code in Python:

PY
Python (What you know)
from dataclasses import dataclass
from typing import Optional

# Dataclass (Python 3.7+)
@dataclass
class Point:
    x: float
    y: float
    label: str = "origin"

p = Point(1.0, 2.0)
print(p)           # Point(x=1.0, y=2.0, label='origin')
p2 = Point(1.0, 2.0)
print(p == p2)     # True — structural equality

# match/case (Python 3.10+)
def describe(shape):
    match shape:
        case {"type": "circle", "radius": r}:
            return f"circle r={r}"
        case {"type": "rect", "w": w, "h": h}:
            return f"rect {w}x{h}"
        case _:
            return "unknown"

# Optional with None
def find_user(id: int) -> Optional[str]:
    return "Alice" if id == 1 else None

user = find_user(1)
if user is not None:
    print(user.upper())
Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

JV
In Java:

record replaces @dataclass — both give constructor, equals, toString automatically

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

JV
In Java:

sealed interface/class restricts which classes can implement/extend it

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

JV
In Java:

Pattern matching in switch (Java 21) matches record types by structure

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

JV
In Java:

Optional<T> makes null-returning functions explicit (vs Python's None)

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

JV
In Java:

'instanceof String s' binds matched variable — no explicit cast needed

Step-by-Step Breakdown

1. Records

A Java record is a concise immutable class. It auto-generates a canonical constructor, getters (without 'get' prefix), equals, hashCode, and toString.

PY
Python
@dataclass
class Point:
    x: float
    y: float
JV
Java
record Point(double x, double y) {}
// Use: new Point(1.0, 2.0)
// Getters: p.x(), p.y() (no 'get' prefix)

2. Sealed Classes

Sealed classes/interfaces restrict which classes can extend them. This enables exhaustive pattern matching — the compiler knows all subtypes.

PY
Python
# Python: just use ABCs or type hints — no enforcement
JV
Java
sealed interface Expr permits Num, Add, Mul {}
record Num(int value)  implements Expr {}
record Add(Expr l, Expr r) implements Expr {}
record Mul(Expr l, Expr r) implements Expr {}

3. Pattern Matching Switch

Java 21 switch can match on types and deconstruct records. With sealed types, the compiler checks exhaustiveness.

PY
Python
match shape:
    case Circle(r=r): return f"r={r}"
    case Rect(w=w, h=h): return f"{w}x{h}"
JV
Java
int eval(Expr e) {
    return switch (e) {
        case Num(var v)    -> v;
        case Add(var l, var r) -> eval(l) + eval(r);
        case Mul(var l, var r) -> eval(l) * eval(r);
    };
}

4. Optional

Optional<T> explicitly models the possible absence of a value. Use map/flatMap/orElse for chaining without null checks.

PY
Python
def find(id) -> Optional[User]:
    ...
if user := find(id):
    print(user.name)
JV
Java
Optional<User> find(int id) { ... }
find(id)
    .map(User::name)
    .orElse("anonymous");
Rule of Thumb
Never return null from a method — return Optional.empty() instead. This makes absence explicit in the API.

Common Mistakes

When coming from Python, developers often make these mistakes:

  • record replaces @dataclass — both give constructor, equals, toString automatically
  • sealed interface/class restricts which classes can implement/extend it
  • Pattern matching in switch (Java 21) matches record types by structure
Common Pitfall
Don't assume Java works exactly like Python. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • record = @dataclass — auto-generates constructor, getters, equals, toString
  • sealed restricts subclasses; enables exhaustive switch pattern matching
  • Pattern matching switch (Java 21) deconstructs records like Python match/case
  • Optional<T> makes nullable returns explicit; chain with map/orElse instead of null checks
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Python code in Java to practice these concepts.
PreviousFinish