java 为什么我需要在通知观察者之前调用 setChanged?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15121071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do I need to call setChanged before I notify the observers?
提问by Shelef
I've recently read about Java's Observableclass. What I don't understand is this: before notifying the observers (notifyObservers()) I must call setChanged(). There is a boolean inside notifyObservers method that requires us to call setChanged. What is the purpose of the boolean value and why must I call setChanged()?
我最近阅读了 Java 的Observable类。我不明白的是:在通知观察者 (notifyObservers()) 之前,我必须调用 setChanged()。notifyObservers 方法中有一个布尔值,需要我们调用 setChanged。布尔值的目的是什么,为什么我必须调用 setChanged()?
回答by Aubin
In a long treatment you may call several times setChanged()but at end, only once notifyObservers(). If, before end, for internal reason you decide to rollback you may choose to call clearChanged(). In the later case, notifyObservers()has no effect.
在长时间的治疗中,您可能会多次调用setChanged()但最后只调用一次notifyObservers()。如果在结束之前,出于内部原因您决定回滚,您可以选择调用clearChanged()。在后一种情况下,notifyObservers()不起作用。
回答by Daniel
setChanged()
setChanged()
Marks this Observable object as having been changed; the hasChanged method will now return true.
将此 Observable 对象标记为已更改;hasChanged 方法现在将返回 true。
notifyObservers()
If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.
如果此对象已更改,如 hasChanged 方法所指示,则通知其所有观察者,然后调用 clearChanged 方法以指示此对象已不再更改。
Basically you use setChanged()
to notify the observer superclass that a change has occurred. Then you call the notifyObservers()
method to fire off to tell observers what is changed.
基本上你setChanged()
用来通知观察者超类发生了变化。然后你调用notifyObservers()
方法来触发来告诉观察者发生了什么变化。
The setChanged() there because it allows for a class to undo changes before notify observers by calling clearChanged()
.
If you didn't setChanged() flag then you are essentially notifying observers and there are no changes detected so they will not respond to the "notify".
setChanged() 在那里是因为它允许一个类在通过调用通知观察者之前撤消更改clearChanged()
。如果您没有 setChanged() 标志,那么您实际上是在通知观察者并且没有检测到任何更改,因此他们不会响应“通知”。
see my code for more explanation:
请参阅我的代码以获取更多解释:
The Main Method public class SpeedRunner {
Main 方法 public class SpeedRunner {
public static void main(String[] args) {
SpeedMonitor monitor = new SpeedMonitor();
// Create a speedometer and register the monitor to it...
SpedoMeter speedo = new SpedoMeter();
speedo.addObserver(monitor);
// Drive at different speeds...
speedo.setCurrentSpeed(50);
speedo.setCurrentSpeed(70);
speedo.setCurrentSpeed(40);
speedo.setCurrentSpeed(100);
speedo.setCurrentSpeed(69);
}
The Observer (object that is informed when something interesting happens):
观察者(当有趣的事情发生时被通知的对象):
//this is the observer since it is observing changes in the speedo.
public class SpeedMonitor implements Observer {
public static final int SPEED_TO_ALERT = 70;
public void update(Observable obs, Object obj) {
SpedoMeter speedo = (SpedoMeter) obs;
if (speedo.getCurrentSpeed() > SPEED_TO_ALERT) {
System.out.println("** ALERT ** Driving too fast! (" + speedo.getCurrentSpeed() + ")");
} else {
System.out.println("... nice and steady ... (" +
speedo.getCurrentSpeed() + ")");
}
}
}
The subject (the the object of interest)
主体(感兴趣的客体)
public class SpedoMeter extends Observable{
private int currentSpeed;
public SpedoMeter(){
currentSpeed = 0;
}
public void setCurrentSpeed(int speed){
currentSpeed = speed;
// setChanged();
notifyObservers();
}
public int getCurrentSpeed() {
return currentSpeed;
}
}
comment out the setChanged() and you will notice nothing is picked up by the observer hence the console is empty.
注释掉 setChanged() ,您会注意到观察者没有拾取任何内容,因此控制台是空的。
See this textbook. Its really good to learn design patterns.
看这本教科书。学习设计模式真的很好。
Bevis, Tony. Java Design Pattern Essentials (Kindle Location 1835). Ability First Limited. Kindle Edition.
贝维斯,托尼。Java 设计模式要点(Kindle 位置 1835)。能力第一有限公司。Kindle版。
回答by Ramhos
the setchanged() is used as indication or flag for changing the state. if it true the notifyObservers() can run and update all the observers.if it false the notifyObservers() is called without calling the setchanged() and the observers will not be notified.
setchanged() 用作更改状态的指示或标志。如果为真,notifyObservers() 可以运行并更新所有观察者。如果为假,则调用 notifyObservers() 而不调用 setchanged() 并且不会通知观察者。
回答by tian
the may reason may be setChanged() is has a protected modifier. Meanwhile, notifyObservers() could be invoked anywhere, even by a observer. Since that, observable and observer may interact with each other with this mechanism.
可能的原因可能是 setChanged() 有一个受保护的修饰符。同时,notifyObservers() 可以在任何地方调用,甚至可以被观察者调用。从那以后,可观察者和观察者可以通过这种机制相互交互。
回答by user3875388
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Observer[] arrLocal;
synchronized (this) {
/* We don't want the Observer doing callbacks into
* arbitrary Observables while holding its own Monitor.
* The code where we extract each Observable from
* the ArrayList and store the state of the Observer
* needs synchronization, but notifying observers
* does not (should not). The worst result of any
* potential race-condition here is that:
*
* 1) a newly-added Observer will miss a
* notification in progress
* 2) a recently unregistered Observer will be
* wrongly notified when it doesn't care
*/
if (!hasChanged())
return;
arrLocal = observers.toArray(new Observer[observers.size()]);
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
arrLocal[i].update(this, arg);
}
The comment is the reason
评论是理由