我正在开发一个需要Java对象才能拥有事件的程序。我非常熟悉它在C#中是如何工作的,有足够的经验来学习陷阱。
在Java中处理事件有哪些陷阱?它们与C#2.0中的事件有什么不同?
示例:对象更改了事件以提示从所有者对象进行保存。
注意:Java 1.5
答案 0 :(得分:7)
Java没有内置的事件概念,所以最好使用The Observer Pattern的变体。
答案 1 :(得分:3)
在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);
}
答案 2 :(得分:1)
Java没有专门的Event概念。它是通过Observable
+ Observer
行的API实现的。据我所知,Java规范中没有专用的lambda-functer API。
答案 3 :(得分:1)
如前所述,Java没有C#所拥有的delegates and events。但考虑到它是Observer pattern(GoF)的“通用”实现,您可以自己实现它。
the wikipedia page中有关于如何使用java.util.Observable
和java.util.Observer
实现模式的示例。一般的想法是让实现Observer
的类订阅自己的Observable
类。
我经常推出自己的实现,因为它很容易实现,因为你只需要创建一个接口来声明“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 有时被称为< EM>听众)。它提供了两者之间关注点的清晰分离。观察员需要将自己注册到一个可观察者身上。
我能想到的唯一“陷阱”是内存泄漏,即使在Java等内存管理环境中,这种模式也可能导致内存泄漏。这是因为Observers和Observables之间的“引用孤岛”会混淆垃圾收集器而不会尝试从内存中删除对象。删除未使用的观察者总是一个好主意。
答案 4 :(得分:0)
事件在Java中是严格特定于容器的,标准库仅提供通用接口(通常根据特定要求进行扩展)。
关于可以在Java(通常)的上下文中考虑的事件的唯一“问题”是Swing容器(组件)和事件调度。 swing框架是单线程的,你应该不使用事件调度线程(即回调)来在事件监听器中进行计算密集型/高延迟的工作。