skip to content

State in Java

State in Java means an object whose behavior changes with its internal state, as a JDBC Connection does across open, closed and in-transaction. Interviewers ask how it differs from Strategy, since the two look identical in code and differ only in who decides the switch.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What is the State design pattern, and how does it let an object change its behavior when its internal state changes?

level: juniorimportance: must knowfreq 70%

answer

  1. Behavioral pattern: object appears to change its class
  2. Context delegates to current State object
  3. One class per state, no big switch
  4. Transition = swap the current state reference
  5. Open/Closed: new state = new class

basics

~20 s

The State pattern lets an object behave differently depending on what 'mode' it is in. Each mode is its own object with its own version of the methods, and the main object hands work to whichever mode it currently holds.

solid answer

~50 s

The State pattern is a behavioral design pattern that lets an object alter its behavior when its internal state changes, so it appears to change its class. You extract each state into its own class implementing a common State interface, and the main object (the 'context') holds a reference to the current state object and delegates behavior to it. Instead of giant if/else or switch blocks scanning a status field, each state class encapsulates the behavior valid in that state and decides which state to move to next. The result removes conditional branching, keeps each state's rules in one place, and makes adding a new state a matter of writing a new class rather than editing every method. In Java you typically model State as an interface or sealed type; transitions happen by the context (or the state itself) swapping the current state reference.

code

java · 22 lines
java
interface LightState {
    LightState next();
    String color();
}
final class Red implements LightState {
    public LightState next() { return new Green(); }
    public String color() { return "RED"; }
}
final class Green implements LightState {
    public LightState next() { return new Yellow(); }
    public String color() { return "GREEN"; }
}
final class Yellow implements LightState {
    public LightState next() { return new Red(); }
    public String color() { return "YELLOW"; }
}

class TrafficLight {           // the Context
    private LightState state = new Red();
    void tick() { state = state.next(); }   // delegate + transition
    String show() { return state.color(); } // no switch anywhere
}

go deeper

for a junior

Can describe State as 'different behavior in different modes, one object per mode' and recognize it removes big switch statements.

for a middle

Explains the three roles (context, state interface, concrete states), shows delegation, and can write a small state machine in Java.

for a senior

Discusses where transitions belong, trade-offs vs. enum/switch, thread-safety of swapping state, and how sealed types model it cleanly.

for a principal

Frames State within a broader state-machine design, weighs it against table-driven FSMs or workflow engines, and reasons about evolution, testing, and invariants across states.

## The problem State solves Many objects behave differently depending on a *mode* or *condition* they are in. A document can be in **Draft**, **Moderation**, or **Published**; a network connection can be **Open** or **Closed**; a vending machine can be **Awaiting Coin**, **Has Coin**, or **Dispensing**. The naive way to model this is a single field (e.g. `String status`) plus `if`/`switch` statements in every method that check the field and branch. This quickly becomes painful: the same `switch (status)` is copy-pasted into many methods, behavior for one state is scattered across the class, and adding a new state means hunting down and editing every method. This is a classic code smell. ## What the State pattern is The **State pattern** is a *behavioral* design pattern (one of the original "Gang of Four" patterns). Its definition: *allow an object to alter its behavior when its internal state changes; the object will appear to change its class.* It has three roles: 1. **Context** — the main object whose behavior varies (e.g. the connection, the document). It keeps a reference to a *current state* object and delegates the real work to it. 2. **State** — an interface (or abstract type) declaring the operations whose behavior depends on state. 3. **Concrete States** — one class per state, each implementing the State interface with the behavior valid *in that state*, and each responsible for deciding which state comes next (the **transition**). Key idea: the `if`/`switch` on a status field disappears. Instead of *one object with many branches*, you have *many small objects, one per state*, and polymorphism picks the right behavior automatically. ## How a call flows When client code calls a method on the context, the context simply forwards the call to its current state object: `currentState.handle(this)`. The state object does the work appropriate to that state and may tell the context to switch to a new state (`context.setState(new NextState())`). The next call therefore behaves differently — the object "appears to change its class." ## Transitions: who decides? There are two common placements for the transition logic: - **State-driven:** each concrete state knows its valid successors and calls `context.setState(...)`. This keeps transition rules next to the behavior, at the cost of states knowing about each other. - **Context-driven:** the context decides the next state. This centralizes the state machine but can re-grow the conditionals you were trying to remove. ## Why it's good - **Removes conditionals** — replaces sprawling `switch` blocks with polymorphism. - **Single Responsibility** — each state's rules live in exactly one class. - **Open/Closed** — a new state is a new class, not edits across existing methods. - **Explicit, legal transitions** — illegal moves can simply not be coded, or throw. ## Costs - More classes (one per state) — overkill if you have only two trivial states. - Transition logic can be hard to follow if scattered across many state classes. ## Tiny example A `TrafficLight` with `Red`, `Green`, `Yellow` states: calling `next()` on the light delegates to the current state, which returns/sets the following color. No `switch (color)` anywhere. In Java you implement State as an `interface` or, in modern Java, a `sealed interface` with `record`/class implementations, optionally an `enum` when states are simple and fixed.

  • Where should the transition logic live — in the context or in the state objects?
    Both are valid. Putting it in each state keeps transition rules next to the behavior (states must know their successors); putting it in the context centralizes the state machine but risks re-introducing conditionals. Choose by how complex and how shared the transition rules are.
  • When is the State pattern overkill?
    When there are only one or two trivial states with little behavior — a simple boolean or enum with a couple of branches is clearer than a class hierarchy. State pays off once behavior per state is substantial or states are many.

saying these in an interview costs you the question

  • Confusing State with a plain status field plus switch statements — that is exactly what State replaces.
  • Thinking the context implements the varying behavior itself; the whole point is delegation to state objects.
  • Claiming State requires a framework — it is plain OOP, no library needed.
  • Saying the object literally changes its Java class; it changes its current-state reference and only *appears* to change class.

context

open as a page

How does a JDBC Connection illustrate state-dependent behavior, and what happens when you call methods after closing it?

level: middleimportance: must knowfreq 62%

basics

~20 s

A JDBC Connection is either open or closed. While open you can run queries; once you call close(), the same methods become illegal and throw SQLException. So the connection's behavior depends on its open/closed state.

open as a page

State and Strategy patterns are structurally almost identical. How do they differ, and how do you decide which one you're using?

level: seniorimportance: must knowfreq 65%

basics

~20 s

They look the same — both delegate to a swappable object behind an interface. The difference is intent: Strategy is an algorithm the client picks and usually keeps fixed; State is a mode the object switches between itself as conditions change, with the states often driving the transitions.

open as a page

In Java, what are the trade-offs of implementing a State machine with an enum versus separate state classes (or a sealed interface)?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Java enums can give each constant its own method body, making a compact, type-safe state machine with no extra files — great for a fixed set of simple states. Separate classes or a sealed interface scale better when states hold their own data or have rich behavior.

open as a page

When designing a State machine in Java, how do you handle illegal transitions and enforce invariants safely across states?

level: principalimportance: should knowfreq 38%

basics

~20 s

Make illegal moves impossible or loud: each state only implements the operations valid in it, and invalid operations throw a clear exception (like IllegalStateException) instead of silently doing the wrong thing. Keep states immutable and validate transitions in one place.

open as a page