【发布时间】:2009-12-14 21:38:42
【问题描述】:
我正在开发一个需要 Java 对象才能产生事件的程序。我非常熟悉它在 C# 中的工作原理,并且有足够的经验来了解其中的陷阱。
在 Java 中处理事件有哪些陷阱?它们与 C# 2.0 中的事件有何不同?
示例:对象更改事件提示所有者对象进行保存。
注意:Java 1.5
【问题讨论】:
标签: c# java events event-handling
我正在开发一个需要 Java 对象才能产生事件的程序。我非常熟悉它在 C# 中的工作原理,并且有足够的经验来了解其中的陷阱。
在 Java 中处理事件有哪些陷阱?它们与 C# 2.0 中的事件有何不同?
示例:对象更改事件提示所有者对象进行保存。
注意:Java 1.5
【问题讨论】:
标签: c# java events event-handling
Java 没有内置的事件概念,因此最好使用The Observer Pattern 的变体。
【讨论】:
在 C# 中,你应该do like this when you fire an event:
public event SomeDelegate MyEvent;
private void FireMyEvent(MyEventArgs args)
{
var deleg = MyEvent;
if (deleg != null) deleg(args);
}
... 保护自己免受并发修改(以防线程在您检查 MyEvent 的空值并调用它之间删除事件侦听器)。在 Java 中,您可以使用 CopyOnWriteArrayList 来保护自己免受并发修改:
private final CopyOnWriteArrayList<MyEventListener> listeners =
new CopyOnWriteArrayList<MyEventListener>();
private void fireMyEvent(MyEventArgs args){
// Iteration is performed over a snapshot of the list, concurrent
// modifications from other threads are invisible to the iterator
// and will not cause ConcurrentModificationExceptions.
for (MyEventListener listener : listeners)
listener.eventOccurred(args);
}
【讨论】:
如前所述,Java 没有 C# 所具有的 delegates and events。但考虑到它是Observer pattern (GoF) 的“通用”实现,您可以自行实现。
the wikipedia page 中有关于如何使用java.util.Observable 和java.util.Observer 实现模式的示例。一般的想法是让实现Observer 的类自己订阅Observable 类。
我通常推出自己的实现,因为这样做很容易,因为您只需要创建一个接口,声明“可观察”类调用它的方法是注册的“观察者”。下面是一个可观察类的简单示例,它可以注册SimpleObserver 对象并对其执行某种事件:
public class MyObservableClass {
List<SimpleObserver> observers = new ArrayList<SimpleObserver>();
/**
* Registers the observer
*/
public void addObserver(SimpleObserver observer) {
observers.add(observer);
}
/**
* Removes the registered observer (to be nice towards the
* garbage collector).
*/
public void removeObserver(SimpleObserver observer) {
observers.remove(observer);
}
/**
* Notifies the observers with the given data
*/
private void notifyObservers(String data) {
for(SimpleObserver o : observers) {
o.onEvent(data);
}
}
public void doSomething() {
// Do some stuff
String data = "Waffles and pwnies";
// Notify the observers that something happened.
notifyObservers(data)
}
}
...这里是简单的观察者界面。
public interface SimpleObserver {
void onEvent(String data);
}
这可能看起来有点复杂,但好处是 Observable 类不需要知道其他对象正在“监听”它的确切内容(这就是为什么有时将 observers 称为 听众)。它在两者之间提供了一个清晰的关注点分离。观察者需要将自己注册到可观察对象。
我能想到的唯一“问题”是这种模式可能导致的内存泄漏,即使在 Java 等内存管理环境中也是如此。这是因为 Observers 和 Observables 之间的“参考岛”会混淆垃圾收集器并且不会尝试从内存中删除对象。 删除未使用的观察者总是一个好主意。
【讨论】:
Java 没有专门的事件概念。它是通过 API 实现的,类似于 Observable + Observer。据我所知,Java 规范中没有专门的 lambda-functer API。
【讨论】:
事件在 Java 中是严格特定于容器的,标准库仅提供一个通用接口(通常针对特定需求进行扩展)。
关于事件的唯一“陷阱”可以说是在 Java 上下文中(通常)是在 Swing 容器(组件)和事件分派中。 swing 框架是单线程的,您应该不使用事件调度线程(即回调)在事件侦听器中执行计算密集/高延迟的工作。
【讨论】: