SafeListener.java
/**
* SafeListener
* <p/>
* Using a factory method to prevent the this reference from escaping during construction
*
*/
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
void doSomething(Event e) {
System.out.println(e);
}
interface EventSource {
void registerListener(EventListener e);
}
interface EventListener {
void onEvent(Event e);
}
interface Event {
}
}
class CopierEventSource implements SafeListener.EventSource {
public CopierEventSource() {
Thread a = new Thread(new Runnable() {
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sendEvent();
}
}});
this.a = a;
}
Thread a;
SafeListener.EventListener el;
public void startSender() {a.start();}
@Override
public void registerListener(SafeListener.EventListener e) {
el = e;
}
private void sendEvent() {
SafeListener.Event e = new SafeListener.Event() {
};
el.onEvent(e);
}
}
public class ThisSafeListenerRunner {
SafeListener.EventListener el;
public ThisSafeListenerRunner(CopierEventSource source) {
SafeListener safe = SafeListener.newInstance(source);
System.out.println(source.el);
el = source.el;
}
//SafeListener can not be subclassed, no longer able to override doSomething() to create stack overflow.
public static void main(String[] args) {
CopierEventSource ces = new CopierEventSource();
ces.startSender();
new ThisSafeListenerRunner(ces);
}
}