2009-12-14 57 views
2

我正在研究需要Java對象來執行事件的程序。我非常熟悉C#中的這種工作方式,因爲他有足夠的經驗來學習這些陷阱。Java中事件處理的缺陷

在Java中使用事件有哪些缺陷?它們與C#2.0中的事件有什麼不同?

示例:對象更改了事件以提示所有者對象的保存。

注:Java 1.5的

相關:C# event handling (compared to Java)

回答

1

如前所述,Java沒有C#擁有的delegates and events。但考慮到它是Observer pattern(GoF)的「廣義」實現,您可以自己實現它。

the wikipedia page中有關於如何使用java.util.Observablejava.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); 
} 

這可能看起來有點複雜,但它的好處是可觀察到的類並不需要知道什麼確切的其它目的是「聽」到它(這就是爲什麼觀察家有時也被稱爲聽衆)。它提供了兩者之間的清晰分離。觀察員需要向可觀察者註冊。

我能想到的唯一「陷阱」就是即使在像Java這樣的內存管理環境中,該模式可能導致的內存泄漏。這是因爲Observers和Observable之間的「參考島」會混淆垃圾回收器,而不會試圖從內存中移除對象。這是總是一個好主意,刪除未使用的觀察者

1

Java沒有Event的專用概念。它通過沿着Observable + Observer行的API來實現。據我所知,Java規範中沒有專用的lambda-functer API。

0

事件在Java中是嚴格容器特定的,標準庫僅提供通用接口(通常針對特定需求進行擴展)。

關於事件的唯一'gotcha'可以被認爲是在Java的上下文(一般)是在Swing容器(組件)和事件調度。擺動框架是單線程的,並且您期望而不是使用事件調度線程(即回調)在事件偵聽器中執行計算密集型/高延遲工作。

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的NULL的含量,把它之間的事件偵聽器) 。在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); 
} 
0

這是一個關於如何使用Java創建,至少文章是這麼說的自定義事件的鏈接... link

:)