observable的notifyobservers()不触发观察者是因为未调用setchanged()设为true;observer的update()参数为object是java 1.0无泛型的遗留设计;observable线程不安全,遍历时并发修改会出错;jdk 9+弃用它因职责耦合且缺乏现代特性支持。

Observable的notifyObservers()为什么有时不触发观察者?
因为Observable默认是“未标记为已更改”状态,调用notifyObservers()前必须先调用setChanged(),否则内部直接返回,什么也不做。
-
setChanged()只是把一个changed布尔字段设为true,不带任何副作用,容易被漏掉 - 如果在多线程环境下调用,
setChanged()和notifyObservers()之间被其他线程重置(比如另一个clearChanged()),也会静默失效 - 子类重写
notifyObservers()但没调用super.notifyObservers(),同样跳过逻辑
示例:
public void doSomething() {
setChanged(); // 必须有!
notifyObservers("data updated");
}
Observer接口的update()方法参数为什么是Object?
这是Java 1.0遗留设计,当时泛型还没出现,所以update(Observable o, Object arg)第二个参数只能是Object,强制类型转换全靠使用者自己负责。
- 传
null合法,但很多Observer实现没判空,运行时抛NullPointerException - 如果传入自定义对象,接收方得手动
if (arg instanceof MyEvent)判断,容易漏分支 - 和现代API(如
PropertyChangeListener)相比,缺乏编译期类型安全
Observable类线程不安全的具体表现
Observable所有关键方法(addObserver()、deleteObserver()、notifyObservers())都没有同步措施,多线程并发操作会导致ConcurrentModificationException或观察者遗漏通知。
- 常见错误场景:一个线程在遍历
observers列表发通知,另一个线程同时调用deleteObserver()修改列表结构 -
observers是Vector,虽然Vector方法自带synchronized,但遍历时仍需外部同步才能保证迭代安全 - 修复方式不是加
synchronized(this),而是改用Collections.synchronizedList(new ArrayList())并手动同步迭代块
为什么JDK 9+标记Observable为@Deprecated且不推荐使用?
不是因为功能错,而是它把“状态变更”和“通知逻辑”强耦合在同一个类里,违反单一职责;同时缺少对泛型、lambda、异步通知等现代需求的支持。
立即学习“Java免费学习笔记(深入)”;
- 无法像
java.util.concurrent.Flow那样支持背压或取消订阅 - 没有内置线程调度能力,想切到Swing线程或IO线程必须手动包装
- 替代方案更直接:用
java.beans.PropertyChangeSupport(适合属性变更)、Subject(RxJava)、或手写简单的ArrayList<consumer>></consumer>+synchronized通知
真正麻烦的是——你可能已经在老项目里写了几十个extends Observable,而它的setChanged()调用点分散在不同条件分支里,漏一个就难定位。









