java - What's the harm in using Anonymous class? -


the question arose while reading answer question - how join 2 lists in java. answer gave solution

list<string> newlist = new arraylist<string>() { { addall(listone); addall(listtwo); } }; 

reading comments, users said evil , ugly , should not used in production.

i know what's harm in using this? why ugly, evil or bad use in production?


note: asked question because, post referenced old (2008) , answerer away since several months.

except mentioned issues regarding programming style , inheritance misuse, there 1 more subtle problem - inner classes , (non-static) anonymous class instances act closures. means keep implicit reference enclosing class instance. can result in preventing of garbage collection , in end, memory leak.

given example piece of source code:

public interface inner {     void inneraction(); }  public class outer {      public void methodinouter() {}      private inner inner = new inner() {         public void inneraction() {             // calling method outside of scope of anonymous class             methodinouter();           }     } } 

what happens @ compilation time, compiler creates class file new anonymous subclass of inner gets so-called synthetic field reference instance of outer class. generated bytecode equivalent this:

public class outer$1 implements inner {      private final outer outer; // synthetic reference enclosing instance      public outer$1(outer outer) {         this.outer = outer;     }      public void inneraction() {         // method outside of scope called through reference outer         outer.methodinouter();     } } 

such capture of reference enclosing instance happens anonymous classes that never access of methods or fields of enclosing class, such double-brace initialized (dbi) list in question.

this results in fact dbi list keeps reference enclosing instance long exists, preventing enclosing instance being garbage collected. suppose dbi list happens live long time in application, example part of model in mvc pattern, , captured enclosing class example jframe, quite large class lots of fields. if created couple of dbi lists, memory leak quickly.

one possible solution using dbi in static methods, because there no such enclosing instance available in scope.

on other hand, still argue using dbi still not necessary in cases. list joining, create simple reusable method, not safer, more concise , clear.

public static <t> list<t> join(list<? extends t> first, list<? extends t> second) {     list<t> joined = new arraylist<>();     joined.addall(first);     joined.addall(second);     return joined; } 

and client code becomes simply:

list<string> newlist = join(listone, listtwo); 

further reading: https://stackoverflow.com/a/924536/1064809


Comments