Sunday, July 10, 2022

[FIXED] Why does this code cause "this reference" to escape implicitly?

Issue

What does "When the inner EventListener instance is published,so is the enclosing ThisEscape instance." mean?

This quote is from 《java Concurrency in Practice》

public class ThisEscape {
public ThisEscape(EventSource source)
{
    source.registerListener(
            new EventListener(){
                public void onEvent(Event e)
                {
                    doSomething(e);
                }
            }
    );
}

}


Solution

ThisEscape instance is published during construction because doSomething is a method of ThisEscape , which can cause unforeseen problems.

A simple code example, when a event occurs, the ThisEscape object has not yet been built, but since this ThisEscape is registered with the EventSource, then onSomeThing method is triggered, and an NPE is generated because ThisEscape#data has not yet been initialized:

public class ThisEscape {
    static class EventSource {
        private List<EventListener> eventListeners = new ArrayList<>();
        public void registerListener(EventListener eventListener) {
            eventListeners.add(eventListener);
        }
        public void eventHappen(Event event) {
            eventListeners.forEach(eventListener -> {
                eventListener.onEvent(event);
            });
        }
    }
    static class Event {
        public String eventString;
        public Event(String eventString) {
            this.eventString = eventString;
        }
    }
    interface EventListener {
        void onEvent(Event e);
    }
    private List<String> data;
    public void doSomething(Event e) {
        data.add(e.eventString);
    }
    public ThisEscape(EventSource source) {
        source.registerListener(
                new EventListener() {
                    public void onEvent(Event e) {
                        doSomething(e);
                    }
                }
        );
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.data = new ArrayList<>();
    }
    public static void main(String[] args) {
        EventSource eventSource = new EventSource();
        new Thread(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            eventSource.eventHappen(new Event("hello"));
        }).start();
        ThisEscape thisEscape = new ThisEscape(eventSource);
    }
}


Answered By - zysaaa
Answer Checked By - Pedro (PHPFixing Volunteer)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.