Search code examples
javainner-classes

How to avoid creating object only referenced by inner class in Java?


I'm trying to create some system with inner class. My code can be summarized to something like this.

public abstract class A {
    public abstract void doSomething();
}

public class B {
    public final ArrayList<A> list=new ArrayList<A>();
    public B(){
    }
}

public class C {
    private int i;
    public C(B b){
        b.list.add(new A(){
            public void doSomething(){
                i++;
            }
        });
        b.list.add(new A(){
            public void doSomething(){
                System.out.println(i);
            }
        });
    }
}

public static void main (String[] arg) {
    B manager=new B();
    new C(manager);
    new C(manager);
    new C(manager);

}

A is abstract class that will be inherited as inner class (in my original code it is listener class), B is some kind of manager class that hold list of As, and C hold data it's data should be only modified or read by it's inner class and upon initialization it add A to the class B. Code itself works fine. But problem is as there will be various kinds of C something like C2, C3 that does different thing and this leads to my code overwhelmed with thousands of unassigned object new C(manager); this make debugging extra hard and code looks really ugly. So it seems to me my approach in the first place was wrong but have no idea how to avoid this. So how should I change my approach to not have thousands of unassigned objects?


Solution

  • My suggestion is: try not to use constructors to do operations that depend on state (i). Use static functions, and save the state in a separate class (we call it a “context”).

    import java.util.ArrayList;
    
    public class Demo {
    
        // A
        abstract static class InnerListener {
            public abstract void onEvent();
        }
        
        // B
        static class ListenerManager {
            public final ArrayList<InnerListener> listeners = new ArrayList<InnerListener>();
        }
    
        static class SideEffectContext {
            public int i = 0;
        }
        // C
        static class ListenerUtil {
            public static void setupListeners(ListenerManager manager, SideEffectContext context) {
                manager.listeners.add(new InnerListener() {
                    public void onEvent() {
                        context.i++;
                    }
                });
                manager.listeners.add(new InnerListener() {
                    public void onEvent() {
                        System.out.println(context.i);
                    }
                });
            }
        }
    
        public static void main(String[] arg) {
            var manager = new ListenerManager();
    
            var ctxA = new SideEffectContext();
            var ctxShared = new SideEffectContext();
    
            ListenerUtil.setupListeners(manager, ctxA);
            ListenerUtil.setupListeners(manager, ctxShared);
            ListenerUtil.setupListeners(manager, ctxShared);
        }
    }