Return to site

What is ADT? Algebraic Data Types in Java, Explained 🔎

· coding,programmmer
Section image

Ever heard folks rave about ADTs and wondered how that maps to plain old Java? Let’s demystify it—and put it to work with record, sealed, and pattern matching. 💪


What is an Algebraic Data Type? 🧠

An ADT is a way to model data precisely using two building blocks:

1) Product type (AND) ✖️ A type composed of multiple fields—think “A and B”. Mathematically, the number of possible values multiplies.

  • Examples: a 2D point (x AND y), a money amount (value AND currency).
  • In Java: a class or (better) a record.

2) Sum type (OR) ➕ A type that is one of several alternatives—think “A or B”. Mathematically, possibilities add up.

  • Examples: a payment that can be Cash OR Card OR GiftCard.
  • In Java: a sealed interface + record implementations (a tagged union). (Enums are a simpler sum type—great when each case has no or fixed payload.)

Explanation from Reddit

ADTs in Java: Idiomatic Patterns (Java 17–21+) ☕️

Product type → record

  • Reads like data, immutable by default, compact constructor = validations/normalization.

Sum type → sealed hierarchy + record cases

Handle all variants with pattern matching for switch (Java 21, JEP 441):

A classic Sum for outcomes → Result

Great for avoiding nullable returns/exceptions for expected failures.

When should you use ADTs? 🎯

  • Domain modeling: Encode business rules in the type system (states, commands, events).
  • State machines & workflows: e.g., Order = Draft | Paid | Shipped | Cancelled.
  • Parsing & validation: return Ok/Err instead of throwing.
  • Exhaustive branching: you must handle every case—no forgotten else.
  • API design: make illegal states unrepresentable.

Pros ✅

  • Correctness by construction: the compiler checks you covered all cases.
  • Clarity: readers see all possible shapes of a value in one place.
  • Immutability by default with records → easier reasoning, thread-friendlier.
  • Less null, fewer fragile strings: explicit alternatives instead.
  • Refactor-friendly: adding a new variant breaks switches at compile time (good!).

Cons ⚠️

  • More types upfront: small learning curve for teams new to ADTs.
  • Framework friction: older libs may need tweaks for record/sealed (e.g., add Jackson modules/annotations).
  • Extensibility constraints: sealed is closed on purpose (strong for safety, less open for plugin-style extension).
  • Pattern matching requirements: best experience on Java 21+.

Practical tips 🛠️

  • Product = “and” → record (validation in the compact ctor).
  • Sum = “or” → sealed interface + record cases.
  • Prefer exhaustive switch over chains of if.
  • Use ADTs at bounded contexts & API boundaries—they shine where correctness matters.
  • For rich error handling, model Result, Option, Either as sealed hierarchies (or use a well-known library).

Takeaways 💡

  • ADTs = Product (AND) + Sum (OR) to model data precisely.
  • In Java, record (product) + sealed + pattern matching (sum) give you the toolkit.
  • Use them to encode domain rules, enable exhaustive handling, and reduce bugs.
  • You’ll write a bit more types, but ship a lot more confidence.

#️⃣ #Java #ADTs #SealedClasses #Records #PatternMatching #FunctionalProgramming #DomainModeling #CleanCode #SoftwareDesign 🚀