Why were java.util.Observable and java.util.Observer deprecated in Java 9, and what should you use instead?
answer
- Observable is a class -> single-inheritance trap
- Object arg = untyped events, casts everywhere
- setChanged() ceremony before notifyObservers()
- Deprecated Java 9, not removed
- Replace with PropertyChangeSupport or Flow
basics
~20 sThe old Observable/Observer classes were deprecated in Java 9 because they were weak and limited: Observable is a class (so you must extend it), it isn't thread-safe in a useful way, and it passes plain Object events. Use listeners, PropertyChangeSupport, or the reactive Flow API instead.
solid answer
~40 sjava.util.Observable (a class) and java.util.Observer (an interface) were the original Observer-pattern support in Java 1.0, deprecated in Java 9. They have real flaws: Observable is a concrete class, so a subject must extend it, blocking other inheritance; events are untyped (Object), forcing casts; change tracking via setChanged()/notifyObservers() is clumsy and easy to misuse; ordering and concurrency guarantees are weak; and it isn't Serializable-friendly. Modern replacements depend on the need: java.beans.PropertyChangeSupport/PropertyChangeListener for typed property-change notification, framework listener interfaces (e.g. Swing ActionListener), or java.util.concurrent.Flow (the reactive-streams Publisher/Subscriber API) for asynchronous backpressure-aware streams. The library still compiles for backward compatibility but you should not build new code on it.
go deeper
Knows the legacy Observable/Observer were deprecated in Java 9 and that you should use listeners or Flow instead.
Can name the concrete flaws (class not interface, untyped Object args, setChanged ceremony) and map each modern replacement to a scenario.
Explains the inheritance/composition trade-off, the deprecation policy (compiles but discouraged), and picks PropertyChangeSupport vs Flow appropriately with reasoning about sync vs async and backpressure.
Frames the deprecation as part of the JDK's shift toward composition, typed events, and the reactive-streams contract; can discuss migration strategy for legacy Observable-based code at scale.
## What the Observer pattern is The **Observer pattern** is a design pattern where one object (the **subject** or **publisher**) maintains a list of dependents (**observers** or **subscribers**) and notifies them automatically when its state changes. It decouples the thing producing events from the things reacting to them: the subject does not need to know the concrete types of its observers, only that they implement an agreed callback. ## The original JDK support: java.util.Observable / java.util.Observer Java 1.0 shipped two types to support this: - **`java.util.Observer`** — an interface with one method, `void update(Observable o, Object arg)`. An observer implements this to react. - **`java.util.Observable`** — a **concrete class** the subject must *extend*. It holds the observer list and offers `addObserver`, `deleteObserver`, `setChanged()`, and `notifyObservers(Object arg)`. The notification protocol is unusual: a subject must call `setChanged()` to flip an internal "changed" flag before `notifyObservers()` will actually fire; `notifyObservers()` then clears the flag. Forgetting `setChanged()` silently suppresses notifications. ## Why it was deprecated in Java 9 (JDK-8154801) It was deprecated (not removed) for several concrete reasons: 1. **`Observable` is a class, not an interface.** Java has single inheritance, so a subject that extends `Observable` cannot extend anything else. This is the classic "favor composition over inheritance" violation — you are forced into an inheritance relationship just to get notification support. 2. **Untyped events.** Both the `Observable o` and the `Object arg` passed to `update` are untyped. Observers must cast and there is no compile-time guarantee about what they receive. 3. **The `setChanged()` ceremony is error-prone.** The two-step changed-flag protocol is easy to get wrong and surprising. 4. **Weak concurrency and ordering guarantees.** `notifyObservers` invokes observers in an unspecified order; the threading model and what happens if the list changes during notification are not well defined for modern concurrent use. 5. **No serialization / event-model integration.** It predates and does not fit the JavaBeans event model or reactive streams. `@Deprecated` here means: still present and compiling for backward compatibility, but a clear signal not to use it in new code. ## What to use instead (chosen by your actual need) - **Typed property-change notification** — `java.beans.PropertyChangeSupport` (a helper you *compose*, not extend) plus `PropertyChangeListener`. You fire `firePropertyChange(name, oldValue, newValue)` and listeners get a typed `PropertyChangeEvent`. This is the idiomatic single-VM, synchronous replacement. - **Framework listeners** — most UI/IO frameworks define their own listener interfaces (e.g. Swing's `ActionListener`, `ChangeListener`). These are the Observer pattern, just typed and domain-specific. - **Reactive / asynchronous streams** — `java.util.concurrent.Flow` (added in Java 9) defines `Flow.Publisher`, `Flow.Subscriber`, `Flow.Subscription`, and `Flow.Processor`: the standard reactive-streams contract with **backpressure** (the subscriber requests how many items it can handle). Use this for async, possibly-infinite event streams. ## Deriving your own answer A junior should be able to say "the old classes were deprecated; use listeners or Flow." A senior adds *why* (class-not-interface, untyped, setChanged ceremony) and *which replacement for which scenario* (PropertyChangeSupport for sync property changes, Flow for async streams).
- What is the single biggest design flaw of java.util.Observable being a class?Java has single inheritance, so a subject forced to extend Observable cannot extend any other class. It violates 'favor composition over inheritance' — composition-based helpers like PropertyChangeSupport avoid this by being a field you hold rather than a parent you extend.
- If I just need typed property-change notifications inside one JVM, what is the idiomatic replacement?java.beans.PropertyChangeSupport composed into your class, firing PropertyChangeEvents to registered PropertyChangeListeners — synchronous, typed, and no inheritance requirement.
saying these in an interview costs you the question
- Saying it was removed from the JDK (it was only deprecated, still compiles)
- Claiming Observable is an interface (it is a concrete class)
- Recommending you keep using Observable for new code
- Forgetting that notifyObservers does nothing unless setChanged() was called first